5

I am creating an app for the company I work for which will backup the data for some software we supply. It has options to add SQL databases, folders, files and reg keys to the backup job which are then put into a Zip file. There are also options to restore the backup when required.

I am having a problem with the registry backup and restore. I have been through many iterations of trying to get this to work but I have simplified it in a way that best illustrates my problem that I hope someone can help with.

Essentially I am importing a ".reg" file by using the regedit.exe with command line arguments. I have tried doing this by building it with ProcessStartInfo() but it did not work. So to test the problem I am creating a batch file instead and running it as follows:

    File.WriteAllText("ImportReg.bat", "regedit /s /i MyRegFile.reg");
    Process.Start("ImportReg.bat");

This however does not work.

The batch file is created successfully and the REG file is valid. Both files are in the same location as the EXE to so I don't think the issue should be with which directory is being used. If I run the batch file myself from this location it successfully imports the registry file. I am a full admin on the machine I am testing this on.

I have also had issues with exporting from the registry. Some parts of the registry export fine and others don't. However, if I set the export up as a batch file like the import above then it works every time.

Can anyone help with this? I cannot see why my batch file works, but not when it's run via Process.Start. Any suggestions would be massively appreciated.

dcastro
  • 66,540
  • 21
  • 145
  • 155
TheCrimsonSpace
  • 188
  • 1
  • 8
  • Did you verify the exit code of the Process ? you can figure out whats happening by investigating the exit code returned by Process. – Kurubaran Sep 08 '13 at 08:20
  • Does it work if you do `Process.Start("regedit.exe", "/s /i MyRegFile.reg");`? – keyboardP Sep 08 '13 at 08:25
  • Thanks for the responses. Directly running the regedit.exe from Process.Start was how I originally started using this, but in trying to find the problem I started using a batch file to rule out any typo issues with too many/too few quotes or backslashes. It doesn't work either. If I use the command directly from the run box it works fine. – TheCrimsonSpace Sep 08 '13 at 08:39
  • The exit code successfully returns a zero. If I put a PAUSE in the batch file it I can see the command window open and wait for my input before closing. – TheCrimsonSpace Sep 08 '13 at 08:42
  • There's just way too much undiagnosable failure when you do it like this. Using the /s option certainly doesn't help either. Use the .NET RegistryKey class instead. – Hans Passant Sep 08 '13 at 10:51
  • What version of Windows are you running? Vista & higher use a redirection scheme to keep you from actually modifying files in the Windows & Windows\System folders. – Tony Vitabile Sep 23 '13 at 16:53
  • 1) Have you tried using an absolute path to the regfile? 2) Does your application run as admin? It's not enough that the user is admin, the application needs to be elevated as well. – CodesInChaos Sep 23 '13 at 16:57
  • Have you tried to fill in the full path for regedit.exe – Schwarzie2478 Sep 23 '13 at 19:10
  • Why did you create a .bat file? Run regedit directly. – David Heffernan Sep 23 '13 at 19:46
  • @DavidHeffernan How are you suggesting that he passes the /s switch? – Strings Sep 29 '13 at 22:36

3 Answers3

1

Could it be a permissions issue?

Regedit is automatically elevated when you double-click on it. But when running through your program, it is not. Perhaps that's why it lets you export some parts of the regiistry, but not others.

FarmerBob
  • 1,314
  • 8
  • 11
  • I'm not sure. The two parts of the registry I'm trying to export are in the same Subkey and were created by my companies own software - one works, one doesn't. Any idea how I can test this? Also, the key that I CAN export from the app, is the same one that I cannot import via the app. – TheCrimsonSpace Sep 08 '13 at 09:28
0

When a program is run even if the logged on user is an administrator it is not run with elevated permissions. Option A) Change the Process.Start to use 'runas' to elevate the created process

...
using System.Diagnostics;
...

System.Diagnostics.Process proc = new System.Diagnostics.Process();
  proc.StartInfo.FileName        = "C:\\Windows\\system32\\notepad.exe";
  proc.StartInfo.Verb            = "runas"; // Elevate the application
  proc.StartInfo.UseShellExecute = true;
proc.Start();

Option B) To elevate the permissions by adding a manifest file

http://msdn.microsoft.com/en-us/library/bb384691.aspx

To set this linker option in the Visual Studio development environment

  1. Open the project's Property Pages dialog box. For details, see How to: Open Project Property Pages.
  2. Expand the Configuration Properties node.
  3. Expand the Linker node.
  4. Select the Manifest File property page.
  5. Modify the Enable User Account Control (UAC), UAC Execution Level, and UAC Bypass UI Protection properties.

The manifest file will look something like this

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <v3:trustInfo xmlns:v3="urn:schemas-microsoft-com:asm.v3">
        <v3:security>
            <v3:requestedPrivileges>
                <v3:requestedExecutionLevel level="requireAdministrator"/>
            </v3:requestedPrivileges>
        </v3:security>
    </v3:trustInfo>
</assembly>

Option C), add the following code (which uses the verb runas, to respawn your program with it's arguments to elevate a duplicate child process) Windows 7 and Vista UAC - Programmatically requesting elevation in C#

Community
  • 1
  • 1
Strings
  • 1,674
  • 10
  • 16
  • But the calling process needs to be elevated as well, so that needs a manifest as well, or use the other 2 options – Strings Sep 23 '13 at 19:57
  • Why does the calling process need to be elevated? Explorer isn't and manages to start regedit. – David Heffernan Sep 23 '13 at 20:12
  • 1
    Explorer does an awful lot more than just using Process.Start(). eg. Explorer uses the shell registry to execute things, (it even for legacy purposes does a load of DDE stuff to be compatible with Windows3.11) - that's why you can click on all sorts of files, rather than just executables. Comparing any code you write to start a process, with an explorer open operation is not realistic, you wouldn't want to write anything so inefficient or complex – Strings Sep 24 '13 at 06:46
  • Nonsense. Ultimately the explorer process makes a call to CreateProcess. The loader then reads the manifest attached to regedit.exe and handles it. That manifest specifies highestAvailable for the requestedExecutionLevel. Write a simple C++ program that calls CreateProcess passing regedit.exe. Run this C++ program without elevation. Observe the UAC dialog presented for regedit. – David Heffernan Sep 24 '13 at 06:52
  • 1
    1)It's not nonsense, explorer does do more than just CreateProcess. This blog http://blogs.msdn.com/b/oldnewthing/ frequently talks about how contrived explorer has become since its inception. 2)CreateProcess includes the UseShellExecute flag, to provide more "explorer" functionality like reading the shell association table, but it doesn't include many of the compatibility patches. 3) If your process is already elevated then the dialog is not produced a second time, so if you want to control the UAC you have to do it in your process because you can't intercept the manifest UAC. – Strings Sep 29 '13 at 21:54
  • `CreateProcess` does not have a `UseShellExecute` flag. There's no need to manipulate anything when starting `regedit` since `regedit` has the `highestAvailable` option for `requestedExecutionLevel` specified in its manifest. Controlling UAC is perfectly possible. Pass the `runas` verb to `ShellExecute`. It's true that Explorer does more than call `CreateProcess` when a user double clicks. It's the shell, clearly it does more than that. But that's not what we are talking about. It's simple: `regedit` already has a manifest. Do you not believe me? – David Heffernan Sep 29 '13 at 21:59
  • 1) CreateProcess requires a ProcessStartInfo structure, all the other overrides simply create this structure and then call the recall the function. ProcessStartInfo does have a UseShellExecute flag. 2)I know regedit has a manifest. 3)As for using runas, that's in my answer so I'm not sure how you are trying to help me improve my answer – Strings Sep 29 '13 at 22:09
  • CreateProcess is a Win32 api – David Heffernan Sep 29 '13 at 22:19
  • You are of course correct, but now you have me totally confused. This is a c# question so I thought we would be talking about Process.Start, you could of course pInvoke CreateProcess, but what is the point. win32api CreateProcess, c# Process.Start and explorer.exe double click, are all entirely different. How are you trying to improve my answer? – Strings Sep 29 '13 at 22:34
  • You started into the details of explorer, which is not written in C#. Ultimately that calls CreateProcess. My point is that all three options in your answer are pointless because regedit already has a manifest. Read your first comment in this thread. That is factually wrong. That's what I am trying to correct. – David Heffernan Sep 30 '13 at 06:11
  • I started with the details of explorer, because that was the question, and actually with the new windows 8 framework, I know that win32api sits on top of the new core OS, so it's possible that Explorer no longer calls CreateProcess either. **Actually I believe the code in the question should work**, I can't see anything wrong with it! So my answer was for his top tier question simply explaining the difference between an explorer click, and a Process.Start call in case that helped the OP realise how he had disrupted his OS (perhaps by deleting the regedit manifest, or something else) – Strings Sep 30 '13 at 11:49
  • Read your first comment in this thread. That is factually wrong. Do you agree? – David Heffernan Sep 30 '13 at 11:55
  • No I don't think it's wrong. A batch file should be elevated if it is going to run multiple high level processes, that way you elevate the process and get one UAC, rather than running a user level batch process spawning processes which will each open their own UAC. – Strings Sep 30 '13 at 16:11
  • That's not what you said. You said that the calling process needed to be elevated. In any case, this batch file calls only one executable. It would just have been easier to admit that you were wrong. Everyone is wrong sometimes. I deleted an answer today with multiple up votes because it turned out to be wrong. No shame in doing so. If you cannot admit to making a mistake, you cannot learn. – David Heffernan Sep 30 '13 at 16:19
  • I thought the purpose of comments was supposed to be a productive process to improve the quality of an answer given by someone else. Do you actually have an idea of how to **identify** the issue the OP has? or even how to improve my answer? because I still think his code looks like should works. Or are you just trolling me because I gave general advice lacking full details 'batch processes should be elevated if they call processes which require higher privileges so you only get one UAC dialog', and said CreateProcess when I meant Process.Start after you introduced the win32api into a c# Q – Strings Sep 30 '13 at 16:38
  • How does me saying I am totally wrong, and you are a StackOverflow master, in anyway improve my answer? Or are you suggesting my answer should be deleted? That would be odd because my answer is factually correct, and hasn't received any down votes, and for all we know may even have helped the OP to solve his problem. – Strings Sep 30 '13 at 16:43
  • I don't need to be able to answer the question in order to comment on other answers. The question is very weak and cannot definitely be answered. In my view the best course is not to answer such a question. I just pointed out that your answer implied something that I felt was incorrect. Namely that regedit would fail because it would not run elevated. All you had to do was try to absorb that message. Create a .bat file with the content `regedit`. Now try to execute that batch file. You will encounter the UAC elevation dialog. In which case none of the options in your answer can have an impact. – David Heffernan Sep 30 '13 at 16:49
  • Am I suggesting that your answer should be deleted? Well, that's up to you. I don't see that it serves any purpose. – David Heffernan Sep 30 '13 at 16:51
  • I never for a second imagined that regedit would fail because it would not run elevated (unless you have specifically modified system files). I don't think I did imply that, if I did that was a mistake. Just answering questions which will score quick points isn't my purpose on StackOverflow. The OP demonstrated he was using the correct functions, and it wasn't working for some reason, so I thought I would try to help him identify what the cause was on **his** computer. I did that to **help**, rather than score points, perhaps an ethos difference between us – Strings Sep 30 '13 at 16:55
  • Please don't judge my ethos. Your previous comment doesn't match the content of the answer. That answer begins, *When a program is run even if the logged on user is an administrator it is not run with elevated permissions.* Perhaps that was a slip of the tongue. Feel free to edit the answer to improve it. – David Heffernan Sep 30 '13 at 17:03
  • Are you suggesting the sentence should be "When a program is run even if the logged on user is an administrator is not automatically run with elevated permissions, unless it is marked with a SxS manifest" Isn't that kind of the whole point of my answer? – Strings Sep 30 '13 at 17:11
  • It's really not that hard. Regedit already has a manifest that means it will run elevated. Hence all three options in your answer have no impact the the program. Do you agree with me? Also it's not an SxS manifest. That's different. – David Heffernan Sep 30 '13 at 17:32
0

You probably passed "regedit /s /i MyRegFile.reg" as the executable name. Pass "regedit.exe" and arguments "/s /i MyRegFile.reg".

usr
  • 168,620
  • 35
  • 240
  • 369