[I forgot to post this draft back in April 2010. Needless to say I no longer utilize the technique nor can really help now that it's purged from my memory]
I've cobbled together a poor-man's backup solution using PowerShell and robocopy in what I thought was a somewhat resilient solution. Robocopy turned out to be a poor choice based upon my needs and nitpicks but I wanted to outline why to save myself and others a little pain.
This URL describes the bug and relative fix: http://superuser.com/questions/48303/access-denied-error-with-robocopy-as-admin. While using /ZB and /B helps it wasn't solving the problem because the relevant ACLs weren't being created even as late as Windows 7.
robocopy has 3 (relevant) major versions: 2003 Resource Kit (the one I was using 010), Vista/RoboCopy GUI (026), and Windows 7. To make things more complicated, installing RoboCopy GUI on a 2003/XP machine will put robocopy under %windir%system32 which happens to enumerate after the 2003 Resource Kit path. This means you have to explicitly call system32robocopy or rename the resource kit version if you hope to keep the other resource kit tools.
I erroneously thought by adding users to the Backup Operators group, a requirement to use the /B switch, robocopy was creating local shadow copies. I might have been confusing it with HoboCopy and figured taking a shadow copy snapshot before a robocopy operation would fix the problem. Turns out taking all that time, determining you almost always need to be administrative, and XP's limited ability to easily expose a snapshot as a drive letter/share made this become an incredible deal breaker.
To combat the bug that started this investigation, I initially tried using version 026 of robocopy to no avail. I used every combination of /copyall, /copy:dats, /copy:dt or just /copy:d.
What really fixes the problem is to completely obliterate the destination folder(s) and start over. This would correctly build the relative ACL and prevent the access denied message but it would only be a matter of time until it happened again.
Note: Robocopy is an end-to-end solution whereas I have far more flexibility to shoot myself in the face with this PowerShell script and the Sync Framework in general.
*: This technique negates the solution completely because I'm creating these directories under the user context the script is run in.
Shadow copies aren't used so to run this in a limited user context I still need the user in the Backup Operators group. I will likely work up a solution using shadow copies on the server as I can rather painlessly manipulate them using the Create Method of the Win32_ShadowCopy Class. Sample Powershell v2 script using AlphaVSS behaves much better if you are not using Windows XP too.
I've started toying with the proper Dotfuscator project settings to give me a workable, yet relatively-secure-as-possible package for deploying to private beta testers and the Marketplace. A great starting point for this journey could be found here: http://weblogs.asp.net/bsimser/archive/2010/12/31/dotfuscator-deep-dive-with-wp7.aspx.
Before we start, my project includes a number of 3rd party controls like AppBarUtils, MVVMLight, Funq, and my favorite IrcDotNet (which is the source of this post). The instructions say to use your XAP file as input so we'll follow that. On the far right-hand side of the
Input Files toolbar is
Transform XAML/BAML resources in all assemblies. Click this to turn it off primarily to be thorough. I believe this affects MVVM because it tries to rename Xaml internals that are data bound. Follow the instructions on the
Settings->Global Options screen to set
Disable Control Flow and
Disable Renaming to No to enable them.
Now click the
Build Project toolbar button to build your project. If your XAP includes a signed assembly, you'll be greeted with the following message:
Warning: The strong named input assemblies (or assembly)
<TempDirectory>IrcDotNet.dllwere not resigned. You will need to sign these dotfuscated assemblies manually.
My first instinct was to go to the
Settings->Signing screen, and enable
Re-sign Strong Named Assemblies and point it to IrcDotNet.snk. If you do that you're met with a different message:
Running sn.exe /q /R
Warning: Password protected Strong Name files are not supported sn returned 1. Build Error.
This is the end of the line as far as automation goes. The only recourse is to sign the assembly manually as the original warning states. If you do not resign this file before deployment, your app will not startup properly. Once code hits that signed assembly it simply will not function.
My first approach was to go to the
Control Flow tabs and exclude every assembly other than my own. This produces the same result. Assemblies are reassembled regardless of whether or not any options are applied.
My preferred approach is to go to the
Input tab, right click on each 3rd party assembly and click
Exclude assembly from package. This has a lovely UI effect of removing everything from the screen and pausing while Dotfuscator works its magic. The added bonus? This happens every assembly. The bare minimum would be to only remove those signed assemblies but I took it all the way and removed all 3rd party dlls. These are all open source frameworks so obfuscating them isn't necessary.
Build Project again and the app starts! Inspecting the result in IL Spy gives me a runtime error on decompile, meaning control flow is on and teh IP iz protectordez. My app also uses localization and
Smart Obfuscation automatically disables renaming for my localization resources so no extra legwork is needed to exclude them.
In summary if you don't need to obfuscate 3rd party assemblies, simply exclude them from the
Input tab rather than trying to exclude them in the individual obfuscation tabs.
Ilasm is still ran on the assemblies which triggers the need to re-sign them.
I chose a cheesy name to spoof on one of my favorite films lately, Team America: World Police. The project likely wouldn't exist if it wasn't for the pioneering efforts of Jeremiah Morrill on the XDA forums. I used the Homebrew project, built by daveux here. The primary reason I chose it was a more 1:1 with the System.Net namespace to use one project for both Windows and Windows Phone (or Silverlight or whatever until the Portable Library Projects bake into VS 2010 SP1).
I'm in the process of determining if I want to use CodePlex or BitBucket and I'm really torn. Bitbucket has awesome small features like merging usernames and a slightly better issue tracker (2 extra fields whee) with external services support as well like being able to track things via Google Analytics. I may just release to both initially just to see which gets picked up or used more often but that may bite me in the ass.
As of today the app works connecting to the very first server created in the settings factory. The very first thing I want to get done after this is use real settings stored in isolated storage and build the UI to change it. I'd like to do that before taking off the reigns and publishing for real but I'll see how that goes.
I could try to explain the UI but screenshots would serve a better purpose of landscape and portait mode respectively:
I'm using the excellent Chillen font, one I've dubbed the new Comic Sans so we'll see how long that sticks. At least initially I hope to have multiple servers as pages with their own pivot controls for channel and query messages. DCC and CTCP commands aren't supported at all and I don't really parse channel events yet except topic changes but things are slowly coming together now that the networking infrastructure is somewhat stable.
I am looking for testers but there's some pretty big caveats. You need developer sideloading access to your phone, either through ChevronWP7 or normal marketplace unlock. I do not have any clue what will happen to this codebase after NoDo hits but I believe native support should still be possible. That puts me in a rush to try to finish something to at least incubate as people use it and luckily I could work on a WPF/SL port reusing almost all of the code.
I primarily posted this just to have a place to link to those screenshots for posterity since I couldn't seem to figure out how to store local images in codeplex or bitbucket. My n00bness is showing...
I almost struggled with a somewhat SEO-friendly title for this but considering I've had at least one request for an explanation, I thought I'd try to post my thoughts in a blog format. The twitter shotgun of a couple of 140 character posts wasn't enough to really convey what was happening.
To set the scene a little bit, I'm making a IRC client for WP7 and one of the core requirements (to me) is "automatically scroll to bottom on output". To achieve this, the ScrollIntoView() method for certain controls like ListBox, ListView, or DataGrid is absolutely crucial. I use MVVMLight and subscribe to an approach of triggering the code-behind from the ViewModel usually through a property update. In this case I chose binding the ListBox's SelectedItem and wired up the SelectionChanged event with code that basically said "when your selection changes, scroll to that since I'm pretty sure that bit of information is what my users (and I) want to see."
The events only fire when something is on screen, which is a tell-tale sign of virtualization to me, and I needed some way around it safely while still utilizing virtualization if possible. The rescue comes in the form of binding the ItemsSource to ICollectionView instead of ObservableCollection as it gives us the MoveCurrentTo() methods as well as filter, sort, and grouping capabilities. When you call MoveCurrentTo, virtualization is turned off so that SelectionChanged can then fire and finish the job.
I will say that ICollectionView is a bit more overhead than most people need which is probably why it isn't pushed as much in samples but I pretty much never bind directly to ObservableCollection anymore.
My motivation for this post is to hopefully have a single place for my thoughts on just what "jailbreaking" means on WP7, what this tool has done, what MS can do, and well pretty much anything else related to the subject.
I have friends invested in WP7 and I completely understand their concern. Another motivation was following a thread from a friend back to this unfortunate starting point: http://twitter.com/#!/ChrisWalshie/status/7967096923226113 (@mikebmcl being my friend in the situation). This was likely in response to this post: http://www.chevronwp7.com/post/1686961408/our-stance-on-piracy. This resulted in one of the other names on the project issuing this post: http://www.istartedsomething.com/20101127/my-thoughts-on-my-thoughts-on-chevronwp7/ leading back to a further post from Mike. That's a lot of concern from both sides.
I don't like the term Jailbreaking in this instance as that seems to infer, based on iPhone and Android definitions, that the carrier lock is also circumvented and you can possibly use your phone anywhere. Let's be clear, this tool is only useful for loading XAP files to the device without a marketplace account. You are still very much "in jail" and tied to the big bad wolf carriers but using the term jailbreaking does give you recent legal protection to a degree.
The problem with opinion in this matter, on both sides, is it doesn't seem to be grounded in complete truth. Comments on Mike's blog talk about a smartphone being like a PC and should be unlocked for all. While at a basic hardware level this is true, what is actually created is more of a specialized hardware device like an Xbox 360. You are given a big walled garden that just so happens to use phone capabilities and the internet but essentially from a legal standpoint you aren't given the keys to this kingdom. You are merely allowed, by the rightful rulers of the realm, to breathe the air they've given you for the low low price of $100 USD.
Windows Phone 7 devices require Windows Live ID to use the cool parts. Windows Phone 7 devices require apps be bought/loaded from the marketplace only. This by nature creates a unique ID between Windows Live ID of the purchaser to the app ID given by the marketplace. Microsoft can literally tell who has purchased what application on which device. This to me, is "game over, man!" for the most part.
At ReMIX Atlanta '10, Brandon Watson was asked a question regarding sideloading of apps besides marketplace for enterprise developers that wish to install apps that the public shouldn't see (think government, high security firms) and at the time they didn't have an answer but were working on it. Part of the answer is what this tool does, unlocking, but consider what this means. Every employee with a wp7 will have to unlock their device to run their company-mandated app? This enterprise app won't be submitted to the marketplace so I don't believe it'd be as trackable. We're essentially saying here "the piracy that matters (i.e. marketplace content) is covered" but the question somewhat remains about where that leaves the private enterprise.
I didn't bring ReMIX to hold Brandon or MS to a firm answer, just that steps can still be made to "tighten up the graphics" so to speak. Worst case, this tool is bringing exposure to the real risks you face as an appdev on the WP7 marketplace.
Here are what I believe are steps to mitigate piracy in any wp7 device:
Pre-Post Update: Before I had a chance to finish my thoughts on this post even more statements have been flying on this issue. http://www.winrumors.com/microsoft-using-chevronwp7-unlock-could-render-windows-phone-7-permanently-unusable/ reads as fear to me, like MS would easily "flip a switch" to render your phone useless. I personally read that as "If you're unlocking your phone using this tool, you run the risk of anything happening and a carrier or MS is legally within right to exact anything mentioned" which isn't quite as heavy handed as the comments were leading towards.
I also want to be clear about where I stand. I believe tools like this are a valuable resource. There is a hole that desperately needs to be addressed, not only in downloading XAP files but unlocked devices. Developers talk in code so until you saw a working proof of concept you weren't going to really listen. Mike is a developer on the marketplace so I completely understand his frustration but I consider the backlash on both sides unfortunate and unwarranted. You're both right to some degree and wrong in others. I have deep respect for Mike, the ChevronWP7 team, and the efforts that lead to their discovery after learning about it on XDA. Hopefully civilized discussion on what boundaries should be set can continue versus whatever the hell is happening now.