Dotfuscator and ClickOnce

  • Thread starter Thread starter Stewart Berman
  • Start date Start date
S

Stewart Berman

Microsoft http://msdn.microsoft.com/en-us/library/76e4d2xw(VS.100).aspx says:

Deploying Obfuscated Assemblies
You might want to obfuscate your application by using Dotfuscator to prevent others from reverse
engineering the code. However, assembly obfuscation is not integrated into the Visual Studio IDE or
the ClickOnce deployment process. Therefore, you will have to perform the obfuscation outside of the
deployment process, perhaps using a post-build step. After you build the project, you would perform
the following steps manually, outside of Visual Studio:

Perform the obfuscation by using Dotfuscator.

Use Mage.exe or MageUI.exe to generate the ClickOnce manifests and sign them. For more information,
see Mage.exe (Manifest Generation and Editing Tool) and MageUI.exe (Manifest Generation and Editing
Tool, Graphical Client).

Manually publish (copy) the files to your deployment source location (Web server, UNC share, or
CD-ROM

It appears to be something that can be done with a simple script but I have yet to find one.

Is there a step by step example for doing the above for a simple ClickOnce Windows Forms application
with a single executable? Something like:

1. Build application
2. Run Dotfuscator -- sample command.
3. Run Marge --sample command
4. Manually publish -- [I think this is straight forward but a sample walk through would clarify
it.]

Also, assuming steps (1), (2) and (3) are done why can't the publish wizard be used?
 
Hi Stewart,

My suggestion is to use publish wizard provided by Visual Studio to publish
the ClickOnce application first and then use the dotfuscator to obfuscate
the executable in the publish location. The last step is to use mage to
update and resign the ClickOnce manifests.

The above work except that done by the publish wizard can be written in a
.bat file. The following is a sample. It assumes the publish location is
http://localhost/TestWinForm and the current version is 1.0.0.4. Copy the
certificate file (.pfx) to the publish location. It also assumes that the
password of the certificate file is 1.

========================================
cd c:\inetpub\wwwroot\TestWinForm\TestWinForm_1_0_0_4
md .\temp
copy TestWinForm.exe.deploy .\temp
rename .\temp\TestWinForm.exe.deploy TestWinForm.exe

path of dotfuscator \ dotfuscator /in: .\temp\TestWinForm.exe

mage -u TestWinform.exe.manifest -fd .\temp -cf
..\testwinform_temporarykey.pfx -pwd 1
rename .\temp\TestWinForm.exe TestWinForm.exe.deploy
copy .\temp\TestWinForm.exe.deploy TestWinForm.exe.deploy
del .\temp /Q
rd .\temp /Q

cd ..\
mage -u TestWinForm_1_0_0_4.application -appm
.\TestWinForm_1_0_0_4\TestWinForm.exe.manifest -cf
testwinform_temporarykey.pfx -pwd 1
copy TestWinForm_1_0_0_4.application TestWinForm.application

=========================================

To summarize, the first step is to use the publish wizard to publish the
application. The second step is to copy the certificate file used to sign
the ClickOnce manifest by Visual Studio to the publish location. The third
step is to run the above .bat file in the Visual Studio 2005 Command Prompt
to obfuscate the executable and update and resign the ClickOnce manfiests.

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

Sincerely,
Linda Liu
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
I am a little confused. The publication step sends the application to an external server hosting
our web site. I cannot run command line applications on their server.

How do I use Dotfuscator -- shipped with Visual Studio 2005 -- on my development machine before
publishing to the web site?

I need to run Dotfuscator and Mage on my development machine after the build completes and before
publishing. Is there someway to export the equivalent of a make file for the build process? It
appears that all that is needed is to run Dotfuscator after the compile and link and before creating
and signing the exe and manifest although I would rather do it as part of the publish process than
the build process.

Where is the definition of the build process stored? It seems that the Dotfuscator, manifest
generation and signing could easily be incorporated into the publication process.
 
Hi Stewart,

After spending several hours on this issue, I find a better solution to
your problem.

Firstly, Visual Studio uses MSBuild to build and publish ClickOnce
applications. Please read the following MSDN documents for information on
MSBuild:

"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

Secondly, every Visual Studio project imports the Microsoft.Common.targets
file, which describes the steps to build and publish an application in
common. The Microsoft.Common.targets file resides in the
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\. Open this file with Notepad
and you can see the detailed information on the tasks performed when you
build and publish an application with Visual Studio.

As you can see, there're targets called Build and PublishOnly in the
Microsoft.Common.targets file. Visual Studio uses these two targets to
build and publish projects. The Build target build the project and generate
ClickOnce manifests. So we need to do the obfuscation after the main
assembly is generated and before the ClickOnce manifests are created.

Fortunately, there's a AfterCompile target, which is built after the
Compile target (which means the main assembly has been generated), and
before the GenerateManifets target (which will generate ClickOnce
manifests). The solution is to add a task inside the "AfterCompile" target
to the project file to call the Dotfuscator command line. Open the project
file with Notepad and add the following snippet after the <Import
Project="$(MSBuildBinPath)\Microsoft.CSharp.targets"/>:

<Target Name="AfterCompile">
<Exec Command="path\Dotfuscator /in:
$(IntermediateOutputPath)appname.exe /out: $(IntermediateOutputPath) "/>
</Target>

Save the project file and reload the project in Visual Studio. Clear and
publish the project within Visual Studio. You should see the generated
executable is obfuscated and then published successfully.

In addition, you can execute the MSBuild command in Visual Studio 2005
Command Prompt to build and publish the project. It's equivalent to
building and publishing within VS and what's important is that you can see
detailed information when MSBuild builds and publishs the project which is
always useful. The command line looks like:
msbuild path\projectname.csproj /t:build, publishonly

Please try my suggetion to see if there's any problem.

Sincerely,
Linda Liu
Microsoft Online Community Support
 
<Exec Command="path\Dotfuscator /in:
$(IntermediateOutputPath)appname.exe /out: $(IntermediateOutputPath) "/>
</Target>

This does not work with the Dotfuscator Community Edition shipped with Visual Studio 2005.
 
I did get:
<Target Name="AfterCompile" Condition="'$(Configuration)'=='Release'">
<Exec Command="&quot;$(DotfuscatorBinPath)&quot; /q
&quot;-in:$(ProjectDir)$(IntermediateOutputPath)$(TargetFileName)&quot;
&quot;-out:$(ProjectDir)$(IntermediateOutputPath).&quot;
&quot;-mapout:$(ProjectDir)$(IntermediateOutputPath)$(AssemblyName).Map.xml&quot; -clobbermap:on "
/>
</Target>
sort of working. That is it starts Dotfuscator during the build and all I have to do is press its
build button and then close it.

Unfortunately, if you open the project's properties and do anything Dotfuscator gets kicked off
multiple times. It also gets kicked of a few times after you hit the publish button. So putting
into the build process is not a solution.

How about this:

1. Run a normal build
2. Manually run Dotfuscator put the results back into the bin\release directory

Now what Mage commands need to be run before publishing:
<Target Name='BeforePublish'>
<-- What goes here? -->
</Target>
 
Found out something else. Publish recompiles the application. Running Dotfuscator with Target
Name='AfterCompile' does nothing. Actually, it does dotfuscator the executable in obj\Release and
bin\Release. Unfortunately, when Publish recompiles the application all of the original code is
back in it.
 
I published the application to my development machine and ran the script shown below. The call to
Dotfuscator is commented out because it doesn't work from the command line. If I just hit enter at
the PAUSE the results is still installable from the publish.htm page. However, if I run Dotfuscator
from Visual Studio 2005 and target the ApplicationName.exe in the Temp directory and then hit enter
to run the rest of the script the results will not install. The error message is:
Strong name signature not valid for this assembly ApplicationName.exe
Doesn't the ApplicationName.exe have to be signed again after applying Dotfuscator?

Script:

W:
CD "\Inetpub\website\ApplicationName\ApplicationName_1_0_0_105"
IF NOT EXIST Temp GOTO :SKIPRD
DEL Temp\*.* /Q /S
RM Temp /Q /S
:SKIPRD
MD Temp
COPY ApplicationName.exe.deploy .\Temp\ApplicationName.exe
COPY MONITR01.ICO.deploy .\Temp\MONITR01.ICO
COPY ApplicationName.exe.config.deploy .\Temp\ApplicationName.exe.config
REM "C:\Program Files\PreEmptive Solutions\Dotfuscator Enhanced Community Edition
4.2\dotfuscator.exe"
"/in:W:\Inetpub\website\ApplicationName\ApplicationName_1_0_0_105\Temp\ApplicationName.exe"
"/out:W:\Inetpub\website\ApplicationName\ApplicationName_1_0_0_105\Temp" "-mapout:H:\Visual Studio
2005\Projects\ApplicationName\ApplicationName.Map.xml" -clobbermap:on /q
PAUSE
"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\Mage.exe" -u ApplicationName.exe.manifest
-fd .\Temp -cf "H:\Visual Studio
2005\Projects\ApplicationName\ApplicationName\ApplicationName_TemporaryKey.pfx" -pwd ***
COPY .\Temp\ApplicationName.exe ApplicationName.exe.deploy /Y
COPY .\Temp\MONITR01.ICO MONITR01.ICO.Deploy /Y
COPY .\Temp\ApplicationName.exe.config ApplicationName.exe.config.deploy /Y
DEL Temp /Q
RD Temp /Q
CD ..
"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\Mage.exe" -u
ApplicationName_1_0_0_105.application -appm ApplicationName_1_0_0_105\ApplicationName.exe.manifest
-cf "H:\Visual Studio
2005\Projects\ApplicationName\ApplicationName\ApplicationName_TemporaryKey.pfx" -pwd ***
COPY ApplicationName_1_0_0_105.application ApplicationName.application /Y

The output of the script executing:

C:\>W:

W:\>CD "\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105"

W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105>IF NOT EXIST Temp GOTO :SKIPRD

W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105>MD Temp

W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105>COPY ApplicationName.exe.deploy
..\Temp\ApplicationName.exe
1 file(s) copied.

W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105>COPY MONITR01.ICO.deploy
..\Temp\MONITR01.ICO
1 file(s) copied.

W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105>COPY ApplicationName.exe.config.deploy
..\Temp\ApplicationName.exe.config
1 file(s) copied.

W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105>REM "C:\Program Files\PreEmptive
Solutions\Dotfuscator Enhanced Community Edition 4.2\dotfuscator.exe"
"/in:W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105\Temp\ApplicationName.exe"
"/out:W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105\Temp" "-mapout:H:\VisualStudio
2005\Projects\ApplicationName\ApplicationName.Map.xml" -clobbermap:on /q

W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105>PAUSE
Press any key to continue . . .

W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105>"C:\Program Files\Microsoft Visual
Studio 8\SDK\v2.0\Bin\Mage.exe" -u ApplicationName.exe.manifest -fd .\Temp -cf "H:\Visual Studio
2005\Projects\ApplicationName\ApplicationName\ApplicationName_TemporaryKey.pfx" -pwd ***
ApplicationName.exe.manifest successfully signed

W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105>COPY .\Temp\ApplicationName.exe
ApplicationName.exe.deploy /Y
1 file(s) copied.

W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105>COPY .\Temp\MONITR01.ICO
MONITR01.ICO.Deploy /Y
1 file(s) copied.

W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105>COPY .\Temp\ApplicationName.exe.config
ApplicationName.exe.config.deploy /Y
1 file(s) copied.

W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105>DEL Temp /Q

W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105>RD Temp /Q

W:\Inetpub\WebSite\ApplicationName\ApplicationName_1_0_0_105>CD ..

W:\Inetpub\WebSite\ApplicationName>"C:\Program Files\Microsoft Visual Studio
8\SDK\v2.0\Bin\Mage.exe" -u ApplicationName_1_0_0_105.application -appm
ApplicationName_1_0_0_105\ApplicationName.exe.manifest -cf "H:\Visual Studio
2005\Projects\ApplicationName\ApplicationName\ApplicationName_TemporaryKey.pfx" -pwd ***
ApplicationName_1_0_0_105.application successfully signed

W:\Inetpub\WebSite\ApplicationName>COPY ApplicationName_1_0_0_105.application
ApplicationName.application /Y
1 file(s) copied.
 
Hi Stewart,

Thank you for your replies!
Unfortunately, if you open the project's properties and do anything
Dotfuscator gets kicked off multiple times.

Yes, it is. If you don't like it, you'll have to adopt the first solution I
suggested in my first reply.
Publish recompiles the application.
Yes, it is.
Unfortunately, when Publish recompiles the application all of the
original code is
back in it.

When Publish recompiles the application, the AfterCompile target will also
be built. So if we obfuscate the executable in the AfterCompile target, the
application will be always obfuscated when it is published. If you run the
MSBuild.exe command in the VS2005 Command Prompt to publish the
application, you'll see the detailed information on the execution of the
tasks.
Doesn't the ApplicationName.exe have to be signed again after applying
Dotfuscator?

After applying Dotfuscator, only the application manifest and deployment
manifest must be updated and resigned.
The error message is:
Strong name signature not valid for this assembly ApplicationName.exe

It looks like you strong-name the assembly. I have tried to strong-name an
executable and apply dotfuscator on it. The result is that the executable
can't run at all. This is just the purpose of strong name signing, i.e. a
strong named assembly could not be changed once it is generated. Any way,
it's not recommended to strong-name application EXE assemblies.


Sincerely,
Linda Liu
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
Linda Liu said:
Dotfuscator?

After applying Dotfuscator, only the application manifest and deployment
manifest must be updated and resigned.

Strong name signature not valid for this assembly ApplicationName.exe

It looks like you strong-name the assembly. I have tried to strong-name an
executable and apply dotfuscator on it. The result is that the executable
can't run at all.

This occurs because obfuscation changes the binary by renaming all of the
symbols within in and thus the assembly no longer hashes to the original
value of the strong name signature. Whenever a strong named assembly is
obfuscated it must be resigned after the obfuscation has taken place in order
that a new strong name signature is generated. This also applies to
Authenticode signing of assemblies that you wish to obfuscate.
 
I removed the strong-name and I was able to Dotfuscator the application and still install it.

Unfortunately, I hit another problem with the Dotfuscator code:

Thread: 1 | 20090727 14:33:59.484: Unable to access application's settings
System.Configuration.SettingsPropertyNotFoundException: The settings property 'IsInitialized' was
not found.
at System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
at System.Configuration.SettingsBase.get_Item(String propertyName)
at System.Configuration.ApplicationSettingsBase.GetPropertyValue(String propertyName)
at System.Configuration.ApplicationSettingsBase.get_Item(String propertyName)
at k.m()
at e.h()

Thread: 1 | 20090727 14:34:14.796: Unable to save settings:
System.Configuration.SettingsPropertyNotFoundException: The settings property 'DefaultDuration' was
not found.
at System.Configuration.SettingsBase.SetPropertyValueByName(String propertyName, Object
propertyValue)
at System.Configuration.SettingsBase.set_Item(String propertyName, Object value)
at System.Configuration.ApplicationSettingsBase.set_Item(String propertyName, Object value)
at k.b(Int32 A_0)
at e.d()

It appears Dotfuscator strips something out of the executable that is needed to get settings. The
error thrown when trying to set the value of a setting is because the name/value pair was not added
to the collection of settings due to the first error.
 
I was able to apply a strong name to the application's executable by not doing it in Visual Studio
but as part of the script I was using to run Dotfuscator. So the steps are:'
1. Publish from Visual Studio
2. Apply Dotfuscator
3. Apply strong name to executable
4. Update the .application and .manifest files via Mage.exe.
5. Install

Unfortunately, Dofuscator makes the application unable to access Settings. It appears that the
entire exercise of trying to use Dofuscator for ClickOnce was futile as the results does work
anyway.
 
When Publish recompiles the application, the AfterCompile target will also
be built. So if we obfuscate the executable in the AfterCompile target, the
application will be always obfuscated when it is published. If you run the

I added this to the project file:
<Target Name="AfterCompile" Condition="'$(Configuration)'=='Release'">
<Exec Command='CMD /C "H:\Visual Studio 2005\Projects\AfterCompileLog.cmd"'></Exec>
</Target>
Where AfterComileLog.cmd contained:
ECHO AfterCompile >> "H:\Visual Studio 2005\Projects\AfterCompile.log
DATE /T >> "H:\Visual Studio 2005\Projects\AfterCompile.log
TIME /T >> "H:\Visual Studio 2005\Projects\AfterCompile.log

I then did a Clean, Build and Publish.

Build activated AfterCompile once.

Publish activated AfterCompile five times. Clearly one would not want to run Dotfuscator five
times. Is there someway to determine which of the five calls is the one that should be used -- some
switch that can be tested?
MSBuild.exe command in the VS2005 Command Prompt to publish the
application, you'll see the detailed information on the execution of the
tasks.

If I run:
msbuild /t:publish ApplicationName.vbproj /p:Configuration=Release
The AfterCompileLog.cmd is only called once. Why is it called five times when I hit Publish Now in
Visual Studio 2005?
 
This are the targets listed when MSBUILD runs:
Target CoreResGen
Target CoreCompile
Target AfterCompile
Target _CopyAppConfigFile
Target _CopyManifestFiles
Target CopyFilesToOutputDirectory
Target _CopyFilesToPublishFolder

It appears that the .application and .manifest files are created and signed in the CoreCompile task.
If you run Dotfuscatore in the AfterCompile task wouldn't you also need to update and sign the
..application and .manifest files?
 
It looks like you strong-name the assembly. I have tried to strong-name an
executable and apply dotfuscator on it. The result is that the executable
can't run at all. This is just the purpose of strong name signing, i.e. a
strong named assembly could not be changed once it is generated. Any way,
it's not recommended to strong-name application EXE assemblies.

It turns out strong-naming the application exe is required if:

isFile = IsolatedStorageFile.GetStore(IsolatedStorageScope.Roaming Or IsolatedStorageScope.User Or
IsolatedStorageScope.Assembly Or IsolatedStorageScope.Domain, Nothing, Nothing)

is to return the same Isolated Storage path after building and publishing as long as the Assembly
version stays the same.

That allows:

isFileStream = New IsolatedStorageFileStream("ApplicationName.xml", FileMode.Open,
FileAccess.ReadWrite, isFile)

to get you the same file after installing a new version of the application.

If strong name is not used, each version of the application references a different Isolated Storage
path even if the assembly version doesn't change.
 
Thanks Joe for your clarification!

Hi Stewart,

Thank you for your prompt response!

As for the strong-named executable assembly, you need to resign it after
applying dotfuscator. Use the Sn.exe command to resign an assembly.
It appears that the .application and .manifest files are created and
signed in the CoreCompile task.

No. The .applicatition file is created in the GenerateDeploymentManifest
target and the .manifest file is created in the GenerateApplicationManifest
target. Both the manifest files are signed in the
_DeploymentSignClickOnceDeployment target.
Publish activated AfterCompile five times. Clearly one would not want to
run Dotfuscator five
times. Is there someway to determine which of the five calls is the one
that should be used -- some switch that can be tested?

I found a better solution is to use the BeforePublish target to apply
dotfuscate on the executable assembly. The BeforePublish target is built
only once when publishing via Publish Wizard. For example:

<Target Name="AfterCompile">
<Exec Command="path\Dotfuscator /in:
$(IntermediateOutputPath)appname.exe /out: $(IntermediateOutputPath) "/>
</Target>

As for accessing application settings from an obsfuscated application, I
can reproduce the problem on my side. A workaround is to use the
ConfigurationManager and Configuration classes to access the application
settings by yourself rather than use the strong-typed setting class
generated by Visual Studio. The following are the methods to read and write
application settings.

string ReadSetting(string sectionGroupName, string sectionName, string
settingName)
{
Configuration configuration =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// Get sectionGroup
ConfigurationSectionGroup sectionGroup =
configuration.GetSectionGroup(sectionGroupName);
// Get section
ClientSettingsSection section =
(ClientSettingsSection)sectionGroup.Sections.Get(sectionName);
// Get setting
SettingElement setting = section.Settings.Get(settingName);
// Read setting value
return setting.Value.ValueXml.InnerText;
}

void WriteSetting(string sectionGroupName, string sectionName,
string settingName,string newvalue)
{
Configuration configuration =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// Get sectionGroup
ConfigurationSectionGroup sectionGroup =
configuration.GetSectionGroup(sectionGroupName);
// Get section
ClientSettingsSection section =
(ClientSettingsSection)sectionGroup.Sections.Get(sectionName);
// write setting
SettingElement setting = section.Settings.Get(settingName);
// Read setting value
setting.Value.ValueXml.InnerText = newvalue;
section.SectionInformation.ForceSave = true;

configuration.Save();
}

The above methods applies to application-scoped settings. For user-scoped
settings, since they are stored in the user.config file in the isolated
storage of the current user, it's a little complex to read and write them.
I'm performing research on this and would get back to you ASAP.


Sincerely,
Linda Liu
Microsoft Online Community Support
 
Stewart Berman said:
I removed the strong-name and I was able to Dotfuscator the application and still install it.

Unfortunately, I hit another problem with the Dotfuscator code:

Thread: 1 | 20090727 14:33:59.484: Unable to access application's settings
System.Configuration.SettingsPropertyNotFoundException: The settings property 'IsInitialized' was
not found.
at System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
It appears Dotfuscator strips something out of the executable that is needed to get settings. The
error thrown when trying to set the value of a setting is because the name/value pair was not added
to the collection of settings due to the first error.

Dotfuscator is not removing anything but by default it is renaming
everything possible in your assembly. This includes any code that uses
reflection to dynamically invoke methods or has properties that need to map
to string literals (such as the application settings code that is auto
generated by Visual Studio)

See the Dotfuscator Knowledge Base articles for a resolution:
http://www.preemptive.com/prb-dotfu...rows-a-settingspropertynotfoundexception.html
or
http://www.preemptive.com/prb-dotfu...ws-a-settingspropertynotfoundexception-2.html
 
I found a better solution is to use the BeforePublish target to apply
dotfuscate on the executable assembly. The BeforePublish target is built
only once when publishing via Publish Wizard. For example:

I would really like to get this working as publishing locally, editing the script to match the
version number, running it manually and then FTP'ing is not the way to do this long term.

I put:
<Target Name="BeforePublish" Condition="'$(Configuration)'=='Release'">
<SAB_MsgBox Prompt="BeforePublish" />
<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; " />
<SAB_MsgBox Prompt="BeforePublish" />
</Target>
into the project file. (SAB_MsgBox is a custom task I put together so I could pause the process and
check what files were created.)

The Publish Now process runs without errors. Unfortunately, the program won't install. The error
log is below. I find it interesting that the fatal error is:
+ File, ApplicationName.exe, has a different computed hash than specified in manifest.
When the warnings are:
* The file named ApplicationName.exe does not have a hash specified in the manifest. Hash
validation will be ignored.
* The file named ApplicationName.exe does not have a hash specified in the manifest. Hash
validation will be ignored.

The manifest file and the application manifest have time stamps later than the Dotfuscatored
executable. Please note that for the purpose of this test I turned off strong name signing.

I check the manifest file and it does not have a hash specified for ApplicationName.exe. However,
neither does one that was created without running Dotfuscator.

Any idea as to what could be going on?


ERROR SUMMARY
Below is a summary of the errors, details of these errors are listed later in the log.
* Activation of http://WEbSite/ApplicationName/ApplicationName.application resulted in
exception. Following failure messages were detected:
+ File, ApplicationName.exe, has a different computed hash than specified in
manifest.

COMPONENT STORE TRANSACTION FAILURE SUMMARY
No transaction error was detected.

WARNINGS
* The file named ApplicationName.exe does not have a hash specified in the manifest. Hash
validation will be ignored.
* The file named ApplicationName.exe does not have a hash specified in the manifest. Hash
validation will be ignored.

OPERATION PROGRESS STATUS
* [7/28/2009 11:09:01 PM] : Activation of
http://WEbSite/ApplicationName/ApplicationName.application has started.
* [7/28/2009 11:09:01 PM] : Processing of deployment manifest has successfully completed.
* [7/28/2009 11:09:01 PM] : Installation of the application has started.
* [7/28/2009 11:09:01 PM] : Processing of application manifest has successfully completed.
* [7/28/2009 11:09:02 PM] : Request of trust and detection of platform is complete.

ERROR DETAILS
Following errors were detected during this operation.
* [7/28/2009 11:09:02 PM] System.Deployment.Application.InvalidDeploymentException
(HashValidation)
- File, ApplicationName.exe, has a different computed hash than specified in
manifest.
- Source: System.Deployment
- Stack trace:
at System.Deployment.Application.ComponentVerifier.VerifyFileHash(String
filePath, Hash hash)
at System.Deployment.Application.ComponentVerifier.VerifyFileHash(String
filePath, HashCollection hashCollection)
at System.Deployment.Application.ComponentVerifier.FileComponent.Verify()
at System.Deployment.Application.ComponentVerifier.VerifyComponents()
at
System.Deployment.Application.DownloadManager.DownloadDependencies(SubscriptionState subState,
AssemblyManifest deployManifest, AssemblyManifest appManifest, Uri sourceUriBase, String
targetDirectory, String group, IDownloadNotification notification, DownloadOptions options)
at
System.Deployment.Application.ApplicationActivator.DownloadApplication(SubscriptionState subState,
ActivationDescription actDesc, Int64 transactionId, TempDirectory& downloadTemp)
at
System.Deployment.Application.ApplicationActivator.InstallApplication(SubscriptionState& subState,
ActivationDescription actDesc)
at
System.Deployment.Application.ApplicationActivator.PerformDeploymentActivation(Uri activationUri,
Boolean isShortcut, String textualSubId, String deploymentProviderUrlFromExtension, BrowserSettings
browserSettings, String& errorPageUrl)
at
System.Deployment.Application.ApplicationActivator.ActivateDeploymentWorker(Object state)

COMPONENT STORE TRANSACTION DETAILS
No transaction information is available.
 
Thanks -- that did the trick.

Joe Kuemerle said:
Dotfuscator is not removing anything but by default it is renaming
everything possible in your assembly. This includes any code that uses
reflection to dynamically invoke methods or has properties that need to map
to string literals (such as the application settings code that is auto
generated by Visual Studio)

See the Dotfuscator Knowledge Base articles for a resolution:
http://www.preemptive.com/prb-dotfu...rows-a-settingspropertynotfoundexception.html
or
http://www.preemptive.com/prb-dotfu...ws-a-settingspropertynotfoundexception-2.html
 
I think I may have found a problem with using BeforePublish. I ran MSBuld using the following
command:
C:\Program Files\Microsoft Visual Studio 8\VC>MSBuild "H:\Visual Studio
2005\Projects\ApplicationName\ApplicationName\ApplicationName.vbproj" /t:build,publish
/p:Configuration=Release /v:diagnostic 1>"H:\Visual Studio
2005\Projects\ApplicationName\MSBuild.log"

The MSBuild output included:
Done building target "BeforePublish" in project "ApplicationName.vbproj".
Target "GenerateManifests" skipped. Previously built successfully.

It does not regenerate the manifest files after the BeforePublish target. Is there a way to force
the manifest files to be generated or updated in the BeforePublish target?

Stewart Berman said:
I found a better solution is to use the BeforePublish target to apply
dotfuscate on the executable assembly. The BeforePublish target is built
only once when publishing via Publish Wizard. For example:

I would really like to get this working as publishing locally, editing the script to match the
version number, running it manually and then FTP'ing is not the way to do this long term.

I put:
<Target Name="BeforePublish" Condition="'$(Configuration)'=='Release'">
<SAB_MsgBox Prompt="BeforePublish" />
<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; " />
<SAB_MsgBox Prompt="BeforePublish" />
</Target>
into the project file. (SAB_MsgBox is a custom task I put together so I could pause the process and
check what files were created.)

The Publish Now process runs without errors. Unfortunately, the program won't install. The error
log is below. I find it interesting that the fatal error is:
+ File, ApplicationName.exe, has a different computed hash than specified in manifest.
When the warnings are:
* The file named ApplicationName.exe does not have a hash specified in the manifest. Hash
validation will be ignored.
* The file named ApplicationName.exe does not have a hash specified in the manifest. Hash
validation will be ignored.

The manifest file and the application manifest have time stamps later than the Dotfuscatored
executable. Please note that for the purpose of this test I turned off strong name signing.

I check the manifest file and it does not have a hash specified for ApplicationName.exe. However,
neither does one that was created without running Dotfuscator.

Any idea as to what could be going on?


ERROR SUMMARY
Below is a summary of the errors, details of these errors are listed later in the log.
* Activation of http://WEbSite/ApplicationName/ApplicationName.application resulted in
exception. Following failure messages were detected:
+ File, ApplicationName.exe, has a different computed hash than specified in
manifest.

COMPONENT STORE TRANSACTION FAILURE SUMMARY
No transaction error was detected.

WARNINGS
* The file named ApplicationName.exe does not have a hash specified in the manifest. Hash
validation will be ignored.
* The file named ApplicationName.exe does not have a hash specified in the manifest. Hash
validation will be ignored.

OPERATION PROGRESS STATUS
* [7/28/2009 11:09:01 PM] : Activation of
http://WEbSite/ApplicationName/ApplicationName.application has started.
* [7/28/2009 11:09:01 PM] : Processing of deployment manifest has successfully completed.
* [7/28/2009 11:09:01 PM] : Installation of the application has started.
* [7/28/2009 11:09:01 PM] : Processing of application manifest has successfully completed.
* [7/28/2009 11:09:02 PM] : Request of trust and detection of platform is complete.

ERROR DETAILS
Following errors were detected during this operation.
* [7/28/2009 11:09:02 PM] System.Deployment.Application.InvalidDeploymentException
(HashValidation)
- File, ApplicationName.exe, has a different computed hash than specified in
manifest.
- Source: System.Deployment
- Stack trace:
at System.Deployment.Application.ComponentVerifier.VerifyFileHash(String
filePath, Hash hash)
at System.Deployment.Application.ComponentVerifier.VerifyFileHash(String
filePath, HashCollection hashCollection)
at System.Deployment.Application.ComponentVerifier.FileComponent.Verify()
at System.Deployment.Application.ComponentVerifier.VerifyComponents()
at
System.Deployment.Application.DownloadManager.DownloadDependencies(SubscriptionState subState,
AssemblyManifest deployManifest, AssemblyManifest appManifest, Uri sourceUriBase, String
targetDirectory, String group, IDownloadNotification notification, DownloadOptions options)
at
System.Deployment.Application.ApplicationActivator.DownloadApplication(SubscriptionState subState,
ActivationDescription actDesc, Int64 transactionId, TempDirectory& downloadTemp)
at
System.Deployment.Application.ApplicationActivator.InstallApplication(SubscriptionState& subState,
ActivationDescription actDesc)
at
System.Deployment.Application.ApplicationActivator.PerformDeploymentActivation(Uri activationUri,
Boolean isShortcut, String textualSubId, String deploymentProviderUrlFromExtension, BrowserSettings
browserSettings, String& errorPageUrl)
at
System.Deployment.Application.ApplicationActivator.ActivateDeploymentWorker(Object state)

COMPONENT STORE TRANSACTION DETAILS
No transaction information is available.




[email protected] (Linda Liu[MSFT]) said:
Thanks Joe for your clarification!

Hi Stewart,

Thank you for your prompt response!

As for the strong-named executable assembly, you need to resign it after
applying dotfuscator. Use the Sn.exe command to resign an assembly.
It appears that the .application and .manifest files are created and
signed in the CoreCompile task.

No. The .applicatition file is created in the GenerateDeploymentManifest
target and the .manifest file is created in the GenerateApplicationManifest
target. Both the manifest files are signed in the
_DeploymentSignClickOnceDeployment target.
Publish activated AfterCompile five times. Clearly one would not want to
run Dotfuscator five
times. Is there someway to determine which of the five calls is the one
that should be used -- some switch that can be tested?

I found a better solution is to use the BeforePublish target to apply
dotfuscate on the executable assembly. The BeforePublish target is built
only once when publishing via Publish Wizard. For example:

<Target Name="AfterCompile">
<Exec Command="path\Dotfuscator /in:
$(IntermediateOutputPath)appname.exe /out: $(IntermediateOutputPath) "/>
</Target>

As for accessing application settings from an obsfuscated application, I
can reproduce the problem on my side. A workaround is to use the
ConfigurationManager and Configuration classes to access the application
settings by yourself rather than use the strong-typed setting class
generated by Visual Studio. The following are the methods to read and write
application settings.

string ReadSetting(string sectionGroupName, string sectionName, string
settingName)
{
Configuration configuration =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// Get sectionGroup
ConfigurationSectionGroup sectionGroup =
configuration.GetSectionGroup(sectionGroupName);
// Get section
ClientSettingsSection section =
(ClientSettingsSection)sectionGroup.Sections.Get(sectionName);
// Get setting
SettingElement setting = section.Settings.Get(settingName);
// Read setting value
return setting.Value.ValueXml.InnerText;
}

void WriteSetting(string sectionGroupName, string sectionName,
string settingName,string newvalue)
{
Configuration configuration =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// Get sectionGroup
ConfigurationSectionGroup sectionGroup =
configuration.GetSectionGroup(sectionGroupName);
// Get section
ClientSettingsSection section =
(ClientSettingsSection)sectionGroup.Sections.Get(sectionName);
// write setting
SettingElement setting = section.Settings.Get(settingName);
// Read setting value
setting.Value.ValueXml.InnerText = newvalue;
section.SectionInformation.ForceSave = true;

configuration.Save();
}

The above methods applies to application-scoped settings. For user-scoped
settings, since they are stored in the user.config file in the isolated
storage of the current user, it's a little complex to read and write them.
I'm performing research on this and would get back to you ASAP.


Sincerely,
Linda Liu
Microsoft Online Community Support
 
Back
Top