I was thinking about how to create a program that would only be valid for X period of time, (within a C# app).
What I was thinking was that you would have the current date as a constant inside the program and it would check to see if it is X days older than that. Naturally I do not want to store the date, or the X outside of the program as it can be tampered with.
What I also do not want to manually change this regularly and recompile and deploy it. So is there a way to set a variable to be the current date when it is compiled?
I could have a batch file that would compile it and deploy the new exe to the distribution server.
Thanks
Precompilation directives are your key here. You could create a constant in your application and have it set when you compile.
Make sure you obfuscate your code, however. Someone could disassemble it easily and tamper with the constant. Another solution is to have your software "phone home" to register itself. That way, the registration info is stored on your server and not their machine. There are also third party packages that perform the same security as you're looking for, but they are expensive!
Check out AssemblyInfo.cs file in the Properties folder in your project:
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Change this to:
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Then, elsewhere in the assembly, use this:
System.Version MyVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
// MyVersion.Build = days after 2000-01-01
// MyVersion.Revision*2 = seconds after 0-hour (NEVER daylight saving time)
DateTime MyTime = new DateTime(2000, 1, 1).AddDays(MyVersion.Build).AddSeconds(MyVersion.Revision * 2);
return string.Format("Version:{0} Compiled:{1:s}", MyVersion, MyTime);
I would go with the "Phone home"-variant. And make that call important. ;)
I mean, some important function in your program (some calculation maybe?) will take place on the server. So if the user decompile the program and remove that "call home" it will render the program useless.
I know that not all programs have those specifications that makes this possible but more than you think in general.
From within your automated build process (you do use an automated build process, right?), had a simple app which generates a 1-line C# class
public struct TimeLimit { public DateTime Date = new DateTime(2009,1,1); }
changing the date automatically, and compile.
Then just refer to TimeLimit.Date in your app.
I know this is a 3 year old question, but just to add my 2 cents. We use a "DateLimit" hard coded in a structure as suggested by James Curran.
But we also use that same "Date" as a simple key to "crypt" and "Decrypt" (more Code and decode) all strings, labels, messages. If some people (We call them Cheaters) want to change the expiration date, They will have to go thru the whole assembly to reenter all those string correctly for the new expiration date. It's not perfect, but the cost to us is now near zero and the cost for the Cheaters is high.
I'd suggest that you have the date in a separate, strong named assembly - then at least the malevolent user will find it hard to disassemble, edit and get your program to use it. Is there a way to have two assemblies validating each other based on strong names?
We kind of use this as a first step in our license control for one of our components. If the calling assembly has the same fingerprint as the license controlled one, we assume that it's being used within our own software and licensing is bypassed. If the calling assembly has a different fingerprint or no print at all, normal license checka are carried through. When I come to think of it, our users could probably disassemble, compile without strong naming and bypass licensing. But then again, all our assemblies are shipped as x86, not CIL - would that change anything?
Our experience is that if you're dealing with corporate customers, no-one can bear the hassle of tampering with your stuff, especially since there is a risk in getting caught. A little goes a long way, our current licensing solution is pretty outdated (the package includes examples for VC5!) but has been a high enough hurdle so far. With consumers, on the other hand, I can imagine that it's a bigger threat.
My initial suggestion seems to spawn more questions that answers - perhaps not that helpful after all. :)
The problem with .Net is that it would be easy to decompile and change the date you want to use has constant. You might need to think to something else.
You could write it in the registry but then the people will edit this value.
They aren't a perfect solution but to have an account that validate with an external (web) server is a good idea.
Related
When troubleshooting our applications, in many situations I cannot be sure what branch the assemblies originally come from, due to an imperfect release cycle and human error.
(We have quite a lot of different bugfix/feature/test/release branches etc. in our TFS).
The PDB-files can help sometimes, in a test environment at least, but sometimes they're missing or outdated / belong to assemblies from another branch.
So, I was trying to think of a way to include the source branch information inside the assembly directly.
Surprisingly, I could not easily find a straight forward way online to accomplish this.
My answer below explains my approach. I would be happy about feedback or alternative solutions.
In short: I created a custom attribute that I put intoAssemblyInfo.cs. Inside the attribute's constructor, the server path for the current assembly is queried from TFS and compiled into it.
It's basically a combination of the following:
Can I add custom version strings to a .net DLL?
How do I get the path of the assembly the code is in?
Get TFS mapped folder of a local sub folder of the solution?
(Note: I cannot post the actual source code due to company restrictions, but I think it's pretty straight forward.)
To get the attribute's value later is unfortunately not as easy as getting the version number from the DLL-file's properties, but at least it is possible now to get the information I need with minimum effort. (I use a small PowerShell script for that.)
I am building a custom installer fed from an xml document...
I know most programmers do not build their own anymore but this is specifically what I was assigned so work with me please. The installer will need to uninstall old versions of the program before it can do its job.
I can obtain registry uninstall strings no problem the problem is that the users building the instructions files are not always going to have an exact display name.
So...
I am using Levenshteins difference to obtain possible matches above 70%, this leaves me open to mistakes. To correct them was hoping i could deserialize the the GUID to obtain the name and make sure I had the right one. or somethign along those lines.
Can someone let me know where to look, or any recomendations on how to make a redundant check in the event the likeness is less than 100% based on levenshteins difference (and confirmed with Hamming difference when words/phrases are of equal length)
Note:
Versions may not be know it is a remove all old versions
Publisher will be identical on all
install location should be network but not guarenteed users love to copy locally
GUIDs do not (or at least SHOULDN'T!) contain any information from the domain they were generated from. These are randomly generated numbers, with a keyspace large enough that they are supposedly guaranteed to be unique.
Unless you have a database or some form of repository to search for this GUID's associated information, a bare GUID is no more useful than an integer ID on a random database table. It's only a identifier.
GUIDs
EDIT
I found a VBS script that may do what you are looking for. This will uninstall an application by it's Registry Id. If your program is written in another language, you can still launch VBS scripts using the System.Diagnostics namespace.
System.Diagnostics.Process.Start("path to script here");
We have a program that is used in one specific industry and has strings that are specific to that industry. We now have the situation where it can be used in another industry and we want to customise the strings for that industry without duplicating our code base.
The problem space appears very similar to localisation. Are we going to have a separate resource assembly for each industry? If so when would we choose which assembly to use, could we do this at install time or would it need to be at compile time?. How do we keep the separate resource assemblies synchronised, so that the same keys to messages appear in each one?
What is the best way to do this?
Let me re-phrase it: you have an industrial application which could be used in various industries and the only things that are different are resources (that is strings, layout, maybe images and sounds). The other code stays the same.
In such case your problem is not just similar it is actually identical to Localization. And as such you can use Satellite Assemblies.
Now, it is up to you if you want to package such created applications separately or distribute one application with both problem spaces.
The first seem more realistic scenario to me - you would need to decide on which .resx file to include at compile time (i.e. during project preparation you would overwrite existing resources with problem-space resources and then proceed with compilation, that should give you different flavors of your application; I would also modify their names in such case).
The latter would require you to manually instantiate ResourceManager at runtime to read from valid satellite assembly - it could be based on some configuration file. It means more work (you would need to actually modify your code) and you will end up distributing both flavors of your application at once, that is you won't have control over how your customers will use it. From the business perspective it could be a little dangerous.
EDIT (Note to self: read whole question carefully)
Somehow I managed to miss install time vs. compile time. I believe compile time is the answer because of the same reason I gave in config-driven switch section: you would package the resources and you won't have any control on how customers use it. Some clever guy would figure it out, that is for sure.
I would recommend having a properties file with key value pairs. Where you currently have industry specific strings, replace them with calls to the properties file. Obviously you would cache these strings in some container. I don't know the C# container - Java would use java.util.Properties.
aerospace.props:
INDUSTRY_NAME=aerospace
INDUSTRY_START_YEAR=1903
manufacturing.props:
INDUSTRY_NAME=manufacturing
INDUSTRY_START_YEAR=1600
We have quite some room for improvement in our application lifecycle management. We don't use TFS or any other suite (shame on us, I know).
Anyway, one of the aspects we currently ponder about is code identity.
In other words: Auditors ask us how we ensure that the software tested and accepted by the departments is exactly and with no alternations the assembly we deploy for productive use and not some tinkered-with version. "That's easy", we say, "it isn't!". Because some configuration variables are set between approval and release, the ClickOnce hashes differ and thus does the whole thing.
That's the story so far, but we want (and have) to get better at what we do, so there's no way around creating our assemblies stateless and oblivious to their environment. But then we will have to set the environment at runtime, our options here are:
Using Application settings and excluding the application configuration from the ClickOnce hash. This sucks because we can't sign the ClickOnce Manifest that way, so users will always be prompted a "watch out, you don't know this guy" kind of message.
Passing Query-String parameters to the application file and using those to distinguish between test and productive environment. I don't like this because it's too open and enables any user to control the important bits (like dbhost or whatever).
Passing in something like "is_test=1" means there's a lot of inline-switching going on, and that on the other hand could mean that the assembly behaves different in production than in test, which brings us back to the start, although we've ensured Assembly-Identity on the way.
I think all that is rather unsatisfying and there must be a better way to do it. How can this be done by little means (meaning without TFS or similar monstrosities)?
I just messed around with the ApplicationDeployment class a little. I think what I have now is pretty close to what I was looking for.
private static void GetDeploymentEnvironment()
{
if (ApplicationDeployment.IsNetworkDeployed)
{
ApplicationDeployment dep = ApplicationDeployment.CurrentDeployment;
FileInfo f = new FileInfo(dep.UpdateLocation.AbsolutePath + ".env");
if (f.Exists)
{
/// read file content and apply settings
}
}
}
This enables me to put a file in the deployment folder (where the .application-file resides) that I can use to override settings. If there is no such file, well...nothing gets overridden. Whatever I do with the content of this file, the Assembly Identity is preserved.
EDIT : Just a hint, as you see this is useful only for applications deployed as Online Only. You cannot start the same ClickOnce .application file from different locations in the Available Offline scenario.
Instead of the major.minor.build.revision format, I'd like to use date and time for version numbers. Something more like day.month.year.time. Is there a way to change the format of the AssemblyVersion attribute in AssemblyInfo.cs?
You can put whatever numbers you want in there (as long as they don't overflow the data types that contain them in memory) and call them whatever you wish. I am not sure why you would want to do this, however, as the standard format usually has some form of the date stored in the build field.
For example, here is the assembly version format that we use where I work:
5.1.729.1
This tells me that this is an assembly from version 5.1 of the library, built on July 29th, and was the first build of the day. Subsequent builds on the same day simply increment the revision field.
The easiest approach is to write you own build task that handles this and then have the .csproj file call your task to update it with your default rules. There's an article on using a custom MSBuild task to increment version numbers that could serve as a guide. We have done a similar thing here in the past and found it to work well.
I don't believe there are any tools included in VS2005 for doing this, though.
I would suggest sticking to the existing scheme for the version numbers as used by AssemblyVersion etc - they have well-known meanings and it might confuse people to go against them.
However, you can easily create your own assembly-level attribute and use that for your date/time. Unfortunately the DateTime type can't be embedded in metadata so you'd probably be best off using a string - but your attribute could convert that to a DateTime for you at execution time.
You could build the relevant fragment of assemblyinfo code in a build script -- it's easy enough using IronPython or F# as a scripting tool.
If you would like to automatically change these versions with a script or something similar. I would suggest using http://www.codeproject.com/KB/macros/versioningcontrolledbuild.aspx
It can be ran from the command line also.