Search code examples
c#wmibcdsafe-modebcdstore

Use C# BCD WMI Provider to SafeBoot Windows


I have scoured the web looking for solutions on how to SafeBoot into Windows using only C#. Since Vista and above, safe booting is controlled using BCD. Ofcourse you could use the commandline tool "bcdedit":

bcdedit /set {current} safeboot Minimal

However I do not want to use this approach. So my question is:

How do I reboot into safe mode using only C#?

I have already looked at this SO post, which has got me started. But I'm still missing pieces to this puzzle.

Any help is greatly appreciated. =)

BCD WMI Provider Reference is of little help.


Solution

  • I wrote up the following code in C# that should allow you to set the safeboot value and delete that value:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Management;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace EditBcdStore
    {
        public class BcdStoreAccessor
        {
            public const int BcdOSLoaderInteger_SafeBoot = 0x25000080;
    
            public enum BcdLibrary_SafeBoot
            {
                SafemodeMinimal = 0,
                SafemodeNetwork = 1,
                SafemodeDsRepair = 2
            }
    
            private ConnectionOptions connectionOptions;
            private ManagementScope managementScope;
            private ManagementPath managementPath;
    
            public BcdStoreAccessor()
            {
                connectionOptions = new ConnectionOptions();
                connectionOptions.Impersonation = ImpersonationLevel.Impersonate;
                connectionOptions.EnablePrivileges = true;
    
                managementScope = new ManagementScope("root\\WMI", connectionOptions);
    
                managementPath = new ManagementPath("root\\WMI:BcdObject.Id=\"{fa926493-6f1c-4193-a414-58f0b2456d1e}\",StoreFilePath=\"\"");
            }
    
            public void SetSafeboot()
            {
                ManagementObject currentBootloader = new ManagementObject(managementScope, managementPath, null);
                currentBootloader.InvokeMethod("SetIntegerElement", new object[] { BcdOSLoaderInteger_SafeBoot, BcdLibrary_SafeBoot.SafemodeMinimal });
            }
    
            public void RemoveSafeboot()
            {
                ManagementObject currentBootloader = new ManagementObject(managementScope, managementPath, null);
                currentBootloader.InvokeMethod("DeleteElement", new object[] { BcdOSLoaderInteger_SafeBoot });
            }
        }
    }
    

    I tested this on my Surface Pro and it seemed to work, as can be verified by running:

    bcdedit /enum {current} /v
    

    Update:

    The code above is just for setting or removing the value that allows you to safeboot.

    After this has been performed, a reboot is required, which can also be accomplished using WMI as is shown here:

    WMI to reboot remote machine

    The answer shows an example for performing this locally or remotely.

    Big thanks to Helen and L-Williams.