c# Clean a registry file .reg to remove duplicate entries - c#

A company I work for sometimes uses super mandatory profiles for their users. Unfortunately this can cause lots of issues with user settings not being saved at log off and so on. To work around this a .reg file is run at startup. For some of these settings regmon was used to record making the settings change and a reg file created from this. The trouble with this is their are lots of duplicate entries making it larger and larger each time this has been done. By the way I didn't implement this procedure I just have to live with it.
I am going to attempt to clean this down to it's minimum but am wondering if anyone has done this before. What I am thinking is, I read the lines into an 2d array so:
[HKEY_CURRENT_USER\Software\CELCAT\CT\SAT\Settings]
"OpenTTVS"="0"
"OTTFrmW"="420"
"OTTFrmH"="321"
becomes:
[HKEY_CURRENT_USER\Software\CELCAT\CT\SAT\Settings], "OpenTTVS"="0"
[HKEY_CURRENT_USER\Software\CELCAT\CT\SAT\Settings], "OTTFrmW"="420"
[HKEY_CURRENT_USER\Software\CELCAT\CT\SAT\Settings], "OTTFrmH"="321"
Then remove duplicates in reverse order so if a setting is changed twice it removes the entries first in the file.
Then sort the array by the hive and output the key every time and the hive when it changes. Sorry if the terminology is wrong.
Will this work? Probably better using a collection rather than an array but you get the idea.

For a first try i would read this .reg file into a tree, just the way regedit looks like. By building up the tree you just check if a node exists. If not, created it else overwrite the existing value.
So you'll get just the last entry which take into effect. After creating this tree, you'll have to read back the current tree and you're ready.
While writing this, i'll got another idea:
Open the .reg file in a texteditor. Replace "[HKEY_CURRENT_USER\" against "[HKEY_CURRENT_USER\JustSomeKeyThatDoesNotExists" and import this file into the registry. Now open the registry and export the whole "[HKEY_CURRENT_USER\JustSomeKeyThatDoesNotExists" back into a file. Open the file and make the first replacement backwards.
Now you'll have a file with unique value in a sorted order. ;-))

You could use a Dictionary of Dictionaries. In pseudo code, you could then do something like this:
Dictionary<String, Dictionary<String, String>> regSettings
Dictionary<String, String> current
for line in sourcefile {
if line.startswith("[") {
if !regSettings.haskey(line) {
regSettings.add(line, new Dictionary<String, String>() )
}
current = regSettings[line]
} else {
key, value = line.split("=")
current[key] = value;
}
}
There are some details to account for (blank lines, comments, poorly remembered function names that should be adjusted for C#...), but that's the basic idea. When you come across a duplicate setting, the later value will replace the older one in the collection. To write the file, just output the reg header, then iterate your collections, writing the top-level key name, followed by all values for that key.

Related

Set a permanent value of a variable without using a database

I don't know how to describe it thoroughly in the title, but I need to set a permanent value of a variable/flag once a process has return true and maybe set some flag in the program itself the value rather than saving it to database. And once that variable/flag has already have that value then the program won't run the process again and just use the value. Is it possible? I'm using VB.Net. I can't use the database because database can be overridden and change values by using query. Thanks in advance!
You can simply use binary/XML serialization in a file to save the state of that variable through your program. Every time you restart your app you can access the value from that file to get its current state.
You can look at this example - http://www.centerspace.net/examples/nmath/csharp/core/binary-serialization-example.php
Basically, you will not save the value in the database but in a file. Anyways you need to persist the value somewhere.
Some ways below
You did not specify if you are afraid that your application or another one could change the value
How I would do it
My ideas below
1)You could use an xml file for example and zip a copy of it with a strong password. Every time you update the first xml you will update also the encrypted zipped xml.You can use a FileSystemWatcher and capture any file change, so if something/someone has changed the file you just get a new copy from the zip
2)You can store the value in the DB and add a trigger to prevent delete/update
for example
-- delete trigger
CREATE TRIGGER Function_Value_Deleted
ON [dbo].[FunctionsValueTb]
AFTER DELETE
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS (
SELECT [Flag] FROM deleted
)
BEGIN
ROLLBACK;
RAISERROR ('Record deletion is not allowed...', 16, 1);
END
END
*You can use also use THROW rather than RAISERROR
**Do the same for the insert and update actions
***You can also store the value into a log table or send an email
I found myself in a situation quite similar to yours a couple of days ago.
In the end, I decided to use the settings functionaly provided by .NET: it is easy to use and maintain, and so far it has given me good results.
Yo can see here what I am talking about:
Best practice to save application settings in a Windows Forms Application
That thread refers to C# but is easily applicable for VB.NET: I just had to follow the same steps in order to add the Settings file:
Right click on the project in Solution Explorer, choose Properties.
Select the Settings tab, click on the hyperlink if settings doesn't
exist. Use the Settings tab to create application settings. Visual
Studio creates the files Settings.settings and
Settings.Designer.settings that contain the singleton class Settings
inherited from ApplicationSettingsBase
And then, from my code, I use the settings like this:
Dim lastExecDate As Date = My.Settings.LastSuccessfulExecution
lastExecDate = lastExecDate.AddDays(1)
// Perform my next execution and do other stuff
My.Settings.LastSuccessfulExecution = lastExecDate
My.Settings.Save()
Next time you retrieve the parameter LastSuccessfulExecution, it will have the updated value.
One more remark, as stated in the post that I linked above:
Note that you need to set the scope property of your settings. If you
select Application scope then Settings.Default.< your property > will
be read-only
Finally, I see that you are using this to store the expiration date of a product, so you don't want the user messing around with it. According to this post, the actual values of the parameters are stored in an Application Data user folder. It is somehow obfuscated since it is not that easy to find and besides it contains a hash on its name... I don't know if that is well hidden enough for you.
If you want the value only to exist in memory when the application is running then you can use the main thread of the application and use:
int slotData = randomGenerator.Next(1, 200);
//to set the data
Thread.SetData(Thread.GetNamedDataSlot("SomeDataKey"), slotData);
//to get the data
int newSlotData = (int)Thread.GetData(Thread.GetNamedDataSlot("SomeDataKey"));
Or you can use the Windows Registry if your app only runs on Windows, if not then you would have to write the value/object to a file and read it from there.

How to get all files from a folder in sorted order in C#.Net? [duplicate]

Is is possible to get files that is ordered same as in Windows Explorer
I know "natural sort", but it's not what I need, I need to get the file list ordered by the same attribute in Windows Explorer, for example:
If I ordered a directory by the attribute "create date", then I will get a file list as below:
name create date file size
1.txt 2012/1/1 125Kb
2.tab 2012/3/2 15Kb
3.bmp 2013/5/5 26Kb
If my windows explorer order file list with the attribute "file size", the the file list would be:
name create date file size
2.tab 2012/3/2 15Kb
3.bmp 2013/5/5 26Kb
1.txt 2012/1/1 125Kb
Could anyone help?
I think this is going to be a lot more complex than you expect. Folder settings are stored in the registry in two places:
HKCU\Software\Microsoft\Windows\Shell\BagMRU
HKCU\Software\Microsoft\Windows\Shell\Bags
The first path contains a structure which reflects the structure of the file system, and the second path contains details about those items, including a REG_BINARY value called "Sort" which records the sort order used for that folder.
See Willi Balenthin's website for details on the structure, including sample code (in Python)
Here's how to get a list of files sorted by their name:
var path = #"C:\windows"; // obviously change this to whatever you want
var files = System.IO.Directory.GetFiles (path).ToList ();
file.Sort();
And that's it!
Here's how you would do it per your given code sample:
var temperaturePressureSignalFilesList = Directory.GetFiles(TemperaturePressureSignalDirectory, "*.txt", SearchOption.TopDirectoryOnly).ToList();
temperaturePressureSignalFilesList.Sort();
using System.Linq;
DirectoryInfo info = new DirectoryInfo(""); FileInfo[] files =
info.GetFiles().OrderBy(p => p.CreationTime).ToArray(); foreach
(FileInfo file in files) {
// DO Something... }
here is the sample code for get files in directory by creation time.
You can get files by size same way.
I guess you are talking about viewing pane in Windows Explorer (it's essentially a Windows File Manager but also known under different name). Some clarification is needed. You can apply your custom sorting on various columns; moreover, you can have multiple viewing panes (windows) open sorted on different columns. Thus, the problem definition is a bit unclear.
Assuming that you know the sorting order in your viewing panes, then you can use System.IO.DirectoryInfo and derived FileSystemInfo[] objects; the latter has files.OrderBy method.
Hope this will help. My best, Alex
If you want natural sort order, you should either P/Invoke StrCmpLogicalW (http://msdn.microsoft.com/en-us/library/bb759947.aspx) or find a managed natural sort algorithm. There is no built-in natural sort in .NET Framework.
I think you cannot know which is the order in the pane (by size, name or whatever), you must read the list and then sort it the way you want or prompt the user to select a sorting attribute.
As Kenny posted Sorting Directory.GetFiles() here is an approach, anyway I still thinking there is no possibly way to know which is the sorting order that user selected in the viewing pane.
I think you would have to write a shell extension for windows explorer that captures sort events on columns and writes that metadata to disk in some structured way. You may have multiple explorer windows open so might be an idea to apply timestamp or id so you know which explorer window you are dealing with. Then in your app read that metadata to get the sort order and apply accordingly. Not easy but doable.

Dictionary list or file access methods or any other method in C#

I have a text file which follows exactly the same type:
**Unique-Key_1**
Value1
Value2
**Unique-Key_2**
Value1
**Unique_Key_3**
Value1
(Please note that the keys and values are not fixed.They might grow in time but one thing is confirmed: It will always follow this structure)
My program wants to search for a key and then retrive all values under it.
I have some viable solutions for this.
1) Should I use a dictionary type and then when my app loads read all keys and values and populate that list?
2) Can I use file access/search methods during run-time and based upon a key , search it and then retrieve values ?
3) Which is the optimum method or is there any methods or any other ways to achieve the same ?
Things to consider:
Does the application have time to load in and parse the file before data is searched? If so, consider parsing the file into a Dictionary. If not, parse the file as needed.
Will the file be very large? If so, parsing it into a Dictionary may take up too much memory. Consider an LRU Cache like Object cache for C#.
Are the keys in the file sorted? If so, a binary search on the file may be possible to speed up the file parses.
Does the data change frequently? If so, parsing the file would guarantee the data is up to date at the cost of slower data access.
Another alternative is to load the values into database tables or a key/value store. This allows the data to be updated piece meal or completely with reasonable access speed if needed at the expense of maintaining and running the database.
Okay, if the file isn't that large I would recommend the Dictionary approach because it's going to make accessing it easier and more efficient at runtime. However, if the file is too large to hold in memory you can use the algorithm provided in this answer to search it.

Trying to create a startup manager using .net 2.0

OK so I'm working on a integrated start-up manager with check boxes, so far this is what i have, it does this on form load:
RegistryKey hklm = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
foreach (string Programs in hklm.GetValueNames())
{
string GetValue = hklm.GetValue(Programs).ToString();
ListViewItem item1 = listView1.Items.Add(Programs);
item1.SubItems.Add(hklm.Name.ToString().Replace("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion", "HKLM"));
item1.SubItems.Add(GetValue);
}
RegistryKey hkcu = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
foreach (string Programs in hkcu.GetValueNames())
{
string GetValue = hkcu.GetValue(Programs).ToString();
ListViewItem item2 = listView1.Items.Add(Programs);
item2.SubItems.Add(hkcu.Name.ToString().Replace("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion", "HKCU"));
item2.SubItems.Add(GetValue);
}
i know its probably a bit sloppy but it seems to work. now what id like to know is, if i have check boxes enabled in the list view... how can i have it:
A: Check the ones that are "enabled"/not check the ones that are "Disabled"
B: make it so when you check one it "enables" it or uncheck one it "disables" it?
OR!
(preferred) make a context menu (right click menu) for disabling and re-enabling each entry (and disabling it would mean making a sub key called something like "Disabled Start" that it would move keys to and enabling them would move them back into the previous key)
i know for enabling/disabling you can just move the key to a different subkey for safe keeping, correct? or do i have this all wrong?
I agree with you . and i world do this if i were you . :)
I think you can either store those disabled keys to a file stored in your app directory. you know , sth like ini file. or you can store them in the registry with a key created by yourself. so you can delete them when uninstalling the manager.
Well the recommended procedure would be so actually save those entries into text files. I storngly suggest that you use Isolated Storage and even stronger if you are going to be building this for a network.
I dunno much about this but I think you could also export the entries into files (which could also be IsolatedStorageFiles) just like this guy seems to have done (look for the "ExportKey" method) and then re-import them. Note that in this case you would still need to have some sort of mechanism to remember the entries so you can show them in the list view.
Regarding the context menu I think this might be what you want, but I just actually google it and running Ubuntu so I can't really try it out before.

Performance issue with accessing Microsoft.Office.Core.DocumentProperties

I have a Excel COM addin which reads the CustomDocumentProperties section of a workbook.
This is how I access a particular entry from the CustomDocumentProperties section
DocumentProperties docProperties = (DocumentProperties)
xlWorkbook.CustomDocumentProperties;
docProperty = docProperties[propName];
The problem is when the CustomDocumentProperties contain more than 8000 entries, the performance of this
code is really bad. I have ran CPU profiler and it showed that the following line takes more than a minute.
docProperty = docProperties[propName];
Does anyone know how to improve the performance of accessing DocumentProperties?
Thanks!
I doubt that there is anything that you could do to improve the performance of the document properties. I believe that it is implemented as a simple list -- not as a dictionary or hash table. In fact, I don't believe that the list is sorted, so with 8000 entries, on average half of them, or 4000, would have to be accessed in order to find the property that you are looking for.
You might consider not using the CustomDocumentProperties as a dictionary. Instead, you might try putting all 8000 of your entries into a custom dictionary, serializing it, and then adding the entire serialized dictionary to the CustomDocumentProperties as a single entry. So to use it, you would access the CustomDocumentProperties, deserialize the dictionary, and then use it repeatedly. When done, if there were any changes to the dictionary, you would have to re-serialize it and save it back to the CustomDocumentProperties, which you would probably only want to do once -- for example, just before saving your workbook. (You might want to put code to re-serialize and save your custom dictionary to the CustomDocumentProperties within the Workbook.BeforeSave event.)

Categories

Resources