Mutex mutex = new Mutex(true, "SomeUniqueID", out mutexIsNew);
A problem arose though when my app started to need to receive command line arguments. How do you also pass those onto the original app? There is a class for this purpose named
"WindowsFormsApplicationBase", it's in Microsoft.VisualBasic.dll
01: Add a class to your project like so:
internal class SingleInstanceApplication : WindowsFormsApplicationBase
private MainForm MainFormInstance;
IsSingleInstance = true;
EnableVisualStyles = true;
MainFormInstance = new MainForm();
MainForm = MainFormInstance;
protected override bool OnStartup(StartupEventArgs eventArgs)
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
02: Add a method to your MainForm class like so:
internal void AcceptCommandArguments(IList
03: Finally change your project source code like so:
static void Main(string args)
SingleInstanceApplication singleInstanceApplication = new SingleInstanceApplication();
In integer used in the database to identify the type of object a table row represents.
The ECO_TYPE table using the name of the class.
Permanent. The name of the class in ECO_TYPE changes when you rename your class, but the integer value never changes.
A way of identifying a class instance across EcoSpace instances. Kind of like a string version of a pointer to an object.
Index of the class in TypeSystem.AllClasses + "!" + the ECO_ID of the instance.
Although the ECO_ID never changes the class index might when you add or remove classes within the model.
I just want to point out that ExternalID and ECO_TYPE are unrelated. When you change your model it does not mean that the ECO_TYPE in your DB must change. Here is an example
01: You create a model with 2 classes in it. The first class is the root, the next is a subclass
ClassA <---- ClassC
02: You generate the DB for the first time. This creates the ECO_TYPE table data with the following values
03: You create an instance of ClassA and ClassB then look in the ClassA table in the DB, you will see something like this
04: Retrieving the ExternalID for each class will return 1!1 and 2!2. This looks like the ECO_TYPE but it isn't!
05: You now change the model like so
ClassA <---- ClassB <---- ClassC
06: You evolve your DB.
The result of this is the following
A: A new entry in ECO_TYPE to enable ECO to see when a class is an instance of ClassB
Note how the types are unchanged. There is no specific order to this list at all. It's a first-come-first-served kind of arrangement.
B: Your ExternalID's now change. The class index returned for each class is
ClassA = 1
ClassB = 2
ClassC = 3
Note that these have no relation at all to the ECO_TYPE. Just because they are both integers means nothing :-)
I hope this clears it up. Remodeling does not mean all your DB type data needs to be updated!
ClassID isn't really required for ECO controlled DB structures because there is always a root table containing the ObjectID + ClassID, but when you use ECO to map to an existing DB structure there needs to be a way to know that object 1234 needs to be fetched from the PERSON table.
So, now that we know why the ExternalID consists of two parts on to why I don't use it (much). If I am writing a website with ECO and I use the ExternalID for my URL like so
The number 23 is determined by looking for the class's index in the list of all classes in the model. This is the problem! If you change your model by adding a new class then your index may change from 23 to 24. Not a big problem for your application, but persistent links to that URL from other sites such as Google will no longer work.
An ExternalID is just like an object's pointer address. When you restart your application that address is no longer valid. ExternalID lives longer than an application restart, but doesn't always live past an application remodeling as explained above.
My tips are as follows:
- For passing object instances around in code, just past the object instance itself.
- For passing a reference to an object to another EcoSpace instance in the same application use ExternalID.
- For storing away a reference for an unknown period of time (config file settings, URLs) add a unique attribute to your class such as an AutoInc and retrieve it using that value in an OCL evaluation.
I'm writing an app that needs me to be able to write to a file and make sure that nobody changes it. The idea that I had was to create 2 classes:
Accepts a targetStream parameter + a privateKeyXml string. I add some space at the beginning of the target stream to reserve it for header info. You then write to the stream as normal (it reports a smaller Length than that of the target stream so your app is unaware of the header). When you close the stream it writes the public key to the stream + an RSA encrypted hash of the data part of the file.
Accepts a sourceStream parameter in the constructor. Just before you read for the first time it will compute an MD5 hash of the data part of the file, and then compare it with the signed hash in the file (which I first decrypt using the stored public key).
These classes therefore provide two functions:
- You can sign a stream, the app can check the stream was signed by you by inspecting the public key within it.
- You can additionally pass a publicKeyXml to the ReadableSignedStream constructor and it will use that instead of the public key within the outer stream, this allows you to ensure nobody has altered your file in any way.
Anyway, to the point. I could always use RsaCryptoServiceProvider.Encrypt() to encrypt the MD5 hash, but whenever I tried to DeCrypt() I would get an exception telling me that my public key was a "Bad key".
It annoyed me for a while, but then I realised something pretty obvious really. The way RSA works is that you are supposed to Encrypt using the Public key and DeCrypt using the Private key. I was using it the wrong way around. The solution was simple....
RsaProvider = new RSACryptoServiceProvider();
MD5 md5 = new MD5CryptoServiceProvider();
byte md5HashBuffer = md5.ComputeHash(dataStream);
byte signedMD5HashBuffer = GetSignedMd5Hash(md5HashBuffer);
private byte GetSignedMd5Hash(byte hashBuffer)
RSAPKCS1SignatureFormatter rsaFormatter = new RSAPKCS1SignatureFormatter();
MD5 md5 = new MD5CryptoServiceProvider();
byte currentMD5HashBufferForFile = md5.ComputeHash(dataStream);
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();
RSAPKCS1SignatureDeformatter rsaDeFormatter = new RSAPKCS1SignatureDeformatter();
if (!rsaDeFormatter.VerifySignature(currentMD5HashBufferForFile, FileEncryptedMd5Hash))
throw new Exception("Someone has messed with the file");
I hope someone finds this useful :-)
So, what was the solution? I tried deleting all PDB files on my hard disk but that didn't do it. In the end manually deleting all of the files previously deployed to my PPC did the trick. Maybe VS couldn't overwrite them or something? No idea, but at least it works now :-)
"There are 10 types of people in the world, those who understand binary and those who don't".
Here is one I came up with myself some years ago and used to use in my newsgroup signature:
"Blessed are the geek, for they shall public class GeekEarth : Earth".