Solved

How to Read and Write 32 bit WoW REG_MULTI_SZ Registry Key on Windows 7 64-Bit OS using C#?

Posted on 2014-02-23
21
1,721 Views
Last Modified: 2014-03-04
I'm a novice C# programmer trying to rework some old VS2008 Source Code (original dev is long gone) that works great on Windows XP, but is now broken since I've upgraded to Win7 64-bit. I'm using VS2012 Express to attempt to migrate the "PathFix.exe" utility. I've upgraded the original Source Code to VS2012 Express, but am having difficulty making sense of what syntax needs to be tweaked for full 64-bit OS compatibility.

I've already tried to run the "PathFix.exe" utility in XP-SP3 Compatibility Mode at the .exe level - doesn't work.

I've found some helpful resources here on EE for successfully reading/writing DWORD registry subkeys in the WOW6432Node without any trouble.

However, I'm still stumped after more hours than I care to admit on how to handle the REG_MULTI_SZ registry subkey I need to prepend a new path string to.

Original XP Code Snippet:
  const string pathGraphics = @"\SOFTWARE\CTool\Applications\graphic\";

        RegistryKey regGraphics = Registry.LocalMachine.CreateSubKey(pathGraphics);
        string[] currentPaths = (string[])regGraphics.GetValue("BackgroundPaths");
        if (currentPaths.Length == 2)
        {
            string[] paths = new string[3];
            paths[0] = bgPath;
            paths[1] = currentPaths[0];
            paths[2] = currentPaths[1];
            regGraphics.SetValue("BackgroundPaths", paths);
            regGraphics.SetValue("LinkPicturePath", bgPath);
            regGraphics.SetValue("ImportPath", bgPath);
        }

Open in new window


New Code:
  string pathArray = string.Empty;

        RegistryKey pathsGraphic = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry32);
        pathsGraphic = pathsGraphic.OpenSubKey(@"\SOFTWARE\CTool\Applications\graphic\");
            if (pathsGraphic != null)
            {
            pathArray = pathsGraphic.GetValue("BackgroundPaths").ToString();

Open in new window

The BackgroundPaths key has two existing strings in it that I need to read and then prepend with a new path for a total of 3 path statements. Problem is I can' t get my head around how to get an array working with .ToString(); in order to get the bgPath string inserted. An Expert's help would definitely be appreciated.

Thanks...
0
Comment
Question by:BrianEsser
  • 11
  • 6
  • 2
21 Comments
 
LVL 40
ID: 39881759
The best way to go for many applications that used to work great on 32-bit and have problems on 64-bit is simply to set the target CPU to x86. They then compile in 32-bit, and Windows 64-bit automatically handle them in WOW so that they work as they used to do.
0
 

Author Comment

by:BrianEsser
ID: 39881890
Thanks for your suggestion James:

Not sure what I'm doing wrong, but it isn't liking me changing to Debug (Config) & x86 (Platform).

Error      10      The OutputPath property is not set for project 'pathFix.csproj'.  Please check to make sure that you have specified a valid combination of Configuration and Platform for this project.  Configuration='Debug'  Platform='x86'.  This error may also appear if some other project is trying to follow a project-to-project reference to this project, this project has been unloaded or is not included in the solution, and the referencing project does not build using the same or an equivalent Configuration or Platform.      pathFix
0
 
LVL 40

Assisted Solution

by:Jacques Bourgeois (James Burger)
Jacques Bourgeois (James Burger) earned 100 total points
ID: 39882932
Do you also have the problem in Release, or only in Debug?

Try with AnyCPU instead of x86, and see if it solves the last error as well as the original one.

If not, when you upgraded, did you upgrade a .csproj file (project) or a .sln file (solution). A solution is a group of projects working together, such as an application and a dll. If the original code was designed around a solution, and you upgraded only the .csproj, then you have a missing project code in your environment.

The following sentence in your error message let me think that this can be your problem: This error may also appear if some other project is trying to follow a project-to-project reference to this project, this project has been unloaded or is not included in the solution.

If you are already working in a solution, then a few programmers found out that they received this error message in the following situation: the output path (Build tab of the project's Properties window) for the 2 projects did not match for a given configuration. If one of the projects is set to compile in bin\Debug but the other one in bin only, then they get that message about the OutputPath.

I hope this helps.
0
 

Author Comment

by:BrianEsser
ID: 39883122
The Error follows both Builds with Release and Debug Configs with x86 Platform.

AnyCPU Builds without any Errors, but the debug/final build .exe fails to write/fix the new path.

I upgraded the VS2K8 .sln File by double clicking on it which initiated VS2K12 launch/upgrade process.

The main problem with the legacy code as upgraded into VS2K12 is the following line of code:
string[] currentPaths = (string[])regGraphics.GetValue("BackgroundPaths");

Open in new window

"currentPaths" is NULL because the subkey "BackgroundPaths" is not returning a result with this syntax. regGraphics.GetVaule appears to be returning the right Registry path (via const string define), but the REG_MULTI_SZ subkey value for "BackgroundPaths" is not being passed to "currentPaths" properly i.e. Null.

While experimenting with other syntax from this site and others I've discovered a successful means to access the "BackgroundPaths" value, but I don't understand yet how to get the multiple values into "currentPaths" Array to write back and prepend the primary path I need in this REG_MULTI_SZ subkey.

Thank you for your support
0
 
LVL 40
ID: 39883196
Because of the way your question was formulated, I concentrated on the 32-bit to 64-bit change.

But looking back at your code with another eye, I see that your are trying to work in LocalMachine. Security is tighter in Windows 7 than it was on XP, and if I am not mislead, you need to be administrator to work with that part of the registry.

Have you tried running the application as an administrator? When running from Visual Studio, you have to start Visual Studio itself as administrator so that the account is passed to the application when you start it with F5 or through the Debug menu.

If BackgroundPaths is a custom registry entry, you might want to move it to the CurrentUser instead of LocalMachine.
0
 

Author Comment

by:BrianEsser
ID: 39883792
Formulating a good question is my biggest challenge, so I apologize for any ambiguity on my part.

Due to the new (perplexing) paradigm of separate 32/64 Bit Registry views using registry redirector and registry reflection I thought that was where I needed to start my ASCII head scratching here on EE. Evidently, this new paradigm can be transparent to legacy 32 Bit applications without much difficulty as long as permissions/UAC isn't in play. However, in my particular case, all users are in the Administrators group on the Win7 computers so I presume this isn't why we can't read the "BackgroundPaths" REG_MULTI_SZ subkey value as needed.

I did try launching VS2k12 as Administrator as well, but there is no difference in the result of my debug session using F11 to step though the code execution.

BackgroundPaths is a custom registry entry resulting from the installation of the application I'm using fixPath.exe to manage, but I don't have control over where it is located.

Thanks for all the great suggestions
0
 
LVL 40
ID: 39883826
Dumb question, but it has to be asked. Have you checked the registry with Regedit to make sure that the key exist and that it contains the values you are looking for?
0
 

Author Comment

by:BrianEsser
ID: 39884143
Haha, that's not a dumb question, but one has to wonder sooner than later if it is "plugged in" and "turned on". Yes, we are good with the BackgroundPaths check in both regedit and regedt32 views.
0
 
LVL 40
ID: 39884178
I overlooked one thing in there. Could be the culprit.

The way I understand it (these things seem to never be clearly explained anywhere), compile with AnyCPU and by default the application will start in 32-bits on a 32-bit system, 64-bit on a 64-bit system.

Compile with x86, and the application with start in 32-bits and register with WOW, but everything underneath has to be 32-bits or AnyCPU.

When  you tried switching to x86, did you do it for all the projects in your solution?

Boy! Why don't they have useful error messages that tell us straight away why something does not work?
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 

Author Comment

by:BrianEsser
ID: 39884242
The syntax below, when used with another REG_SZ type subkey (@"SOFTWARE\Microsoft\Windows NT\CurrentVersion") in LocalMachine, returns the "RegisteredOrganization" subkey value string ("HP") without issue.

The difficulty appears to be related to the "BackgroundPaths" subkey being a REG_MULTI_SZ type.
            string[] pathArray = new string[2];
            RegistryKey pathsGraphic = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry32);
            pathsGraphic = pathsGraphic.OpenSubKey(@"\SOFTWARE\CTool\Applications\graphic\");
            if (pathsGraphic != null)
            {
                pathArray[2] = pathsGraphic.GetValue("BackgroundPaths").ToString();

Open in new window

What this code snippet returns for BackgroundPaths via pathArray[2] in the VS Locals Pane during debug is {string[2]} instead of the two paths as expected.
0
 

Author Comment

by:BrianEsser
ID: 39884279
I just have the one Project in this Solution. However, I'm not exactly confident/clear on how to manipulate Configuration Manager to create the x86 Platform option.Copy Settings from Any CPU for x86 in Configuration Manager? Do I Copy Settings from Any CPU or just leave it blank?

As mentioned in my previous post, why can I read other LocalMachine subkeys with the new updated syntax as currently compiled for AnyCPU Platform?
0
 
LVL 40
ID: 39884640
Personnally, and even more when there is only one project in the solution, I do not set the Platform through the Configuration Manager, I do it through the Build tab of the project's Properties window. Since all the other build settings are there, I do not see the need to do it through the Configuration Manager, unless I work with a solution that has many projects in it. In such a case, the Configuration Manager can be useful because then you have a better picture of the whole solution.

As for the copying of settings from one platform to another, I do not understand it and, I confess, it scares the hell out of me. So I leave that alone. This is not available by the way if you work from the project's Properties window.

Back to your problem with the registry, do you really need to use the registry. I find that the registry is overused and overcharged. There are a few instances where this is the best thing to use, but most of the time, the configuration file of the application is a better place to store data.

Since it is prepared by the environment as you develop your application, you do not end up with the problems that you encounter. It never causes security problems. It is a lot easier to use. And it uses .NET types instead of the C types used in the registry, so you never have to deal with conversion problems.

Unless you absolutely have to use the registry for one reason or another, I would suggest that you give a look to the possibility of using configuration files instead of the registry for your string array storage.
0
 

Author Comment

by:BrianEsser
ID: 39884976
I've found the Build tab per your recommendation and I've updated the settings for 32bit and x86 per the attached screen capture. I ran a Debug Build and ran the .exe out of the Debug BIN with the same failed result.

As for using the Registry, I'm stuck with it since the Legacy Application that PathFix.exe fixes will not be updated to accommodate a Config File in lieu of the Registry. Although, I do concur with your reasoned recommendation completely.

Now if I could just code up the appropriate string array storage syntax I'd be moving past this hurdle and getting some sleep.

Thanks again
x86-32bit-Build-Graphic-2-25-201.png
0
 

Author Comment

by:BrianEsser
ID: 39896298
Still trying to... Read and Write 32 bit WoW REG_MULTI_SZ Registry Key on Windows 7 64-Bit OS using C#...
0
 
LVL 32

Assisted Solution

by:Robberbaron (robr)
Robberbaron (robr) earned 400 total points
ID: 39900196
you seem to be reading the REG_MULTI_SZ differently than i have seen before

http://www.pcreview.co.uk/forums/read-reg_multi_sz-and-reg_sz-types-registry-c-t1381342.html

//pathArray[2] = pathsGraphic.GetValue("BackgroundPaths").ToString();
// have to cast the GteValue object to a string array

string[] pathArray = (string[]) pathsGraphic.GetValue("BackgroundPaths");

foreach (string multival in pathArray )
{
   debug.Print( multival );
}
//or debug.Print(patharray[2]);  //if you just want the third one. as zero based
0
 

Author Comment

by:BrianEsser
ID: 39901394
Thanks robr, this is just the nudge I needed to get me 50% of what I needed.
I've successfully read the two existing paths from "BackgroundPaths" into string "pathArray" and then parsed them out into a new "paths[3]" array to prepend "bgPath".

Now I'm stuck again trying to SetValue in the WOW Registry target "BackgroundPaths" for all three paths with an Unauthorized Access Exception referenced in attached png file.Unauthorized Access Exception occuredPlease Note that I did run my VS2012 Express Dev Environment by r-click Run As Administrator and still received the same Unauthorized Access Exception.
0
 

Author Comment

by:BrianEsser
ID: 39901917
Worked past the Unauthorized Access Exception by adding "true" to the "pathsGraphic" .OpenBaseKey statement to make the subkey writable. Problem now is the way I'm handling it results in a REG_SZ write and not the necessary REG_MULTI_SZ kind. Tried to use RegistryValueKind.MultiString on the Write, but that has thrown a RegistryValueKind Exception.RegistryValueKind ExceptionI've found a C++ code walk through on MSDN Link for Registry Value Types which isn't making sense to me. Specifically, C# syntax to terminate strings with null characters and how many null characters per string (2ea?). The quest continues for the proper way to ...Write 32 bit WoW REG_MULTI_SZ Registry Key on Windows 7 64-Bit OS using C#?
0
 
LVL 32

Accepted Solution

by:
Robberbaron (robr) earned 400 total points
ID: 39902616
with reference to http://msdn.microsoft.com/en-us/library/k23f0345(v=vs.110).aspx
You cannot store a single string value as a RegistryValueKind.MultiString.

the 'value' is an object so you use the array as the value. so the MSDN example is...
    rk.SetValue("MultipleStringValue", new string[] {"One", "Two", "Three"}, RegistryValueKind.MultiString);

pathsGraphic.SetValue("BackgroundPaths",paths,RegistryValueKind.MultiString);

Open in new window

0
 

Author Closing Comment

by:BrianEsser
ID: 39903516
Sure do appreciate EE and their Experts 100% SOLVED
Learned a ton in the process.
Thanks!
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Suggested Solutions

Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now