[C#] User/System 권한으로 레지스트리(Registry) 값 읽어오기
업데이트:
Registry 값 읽어오기
C++ 포스팅 내용과 비교
시스템 권한으로 레지스트리를 읽어오는 방법에대하여 아래 링크에 c++을 이용한 포스팅으로 소개했었다.
- https://hwanine.github.io/c++/Registry-c++/
이번엔 C#에서 레지스트리를 읽어오는 방식에 대하여 다뤄보겠다.
User 권한 방식
아래 코드를 통해 레지스트리 값을 읽고 저장할 수 있다.
Microsoft.Win32 네임스페이스를 사용한다.
using Microsoft.Win32;
// 레지스트리 추출
var readRegKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("{RegistryPath}"); // 레지스트리 경로 입력
var value = readRegKey?.GetValue("{Value}")?.ToString(); // 가져올 값 입력
// 레지스트리 저장
var saveRegKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("{RegistryPath}", true); // 레지스트리 경로 입력
if (!Microsoft.Win32.Registry.CurrentUser.GetSubKeyNames().Select(x => x.Equals(saveRegKey)).Any())
{
Microsoft.Win32.Registry.CurrentUser.CreateSubKey(saveRegKey);
}
saveRegKey?.SetValue("{key}", "{value}"); // 저장할 키와 값 입력
위의 방법으로 레지스트리 값을 읽고 쓸 수 있다. 물론 다른 자료형으로 읽는 방법도 가능하다.
문제점
근데 이 방법으로 사용하면 마찬가지로 시스템 권한일 경우 레지스트리를 읽어오지못한다. 즉, C#으로 윈도우 서비스 개발을 할 경우, 서비스 권한을 유저 권한으로 변경해주지 않으면 System 계정으로 레지스트리에 접근을하여 정상적으로 읽어오지 못한다.
System 권한 방식
아래 코드는 윈도우 서비스에 Local System 계정으로 등록되어있어도 정상적으로 레지스트리를 읽어올 수 있다.
방식은 C++ 방식과 같다.
- 실행된 프로세스 PID를 찾는다.
- 프로세스 ID로 실행자 SID를 찾는다.
- 실행자 SID로 레지스트리를 조회한다.
// 탐색기 프로세스를 찾아 PID를 찾는다.
foreach (Process process in Process.GetProcesses()) // 프로세스 목록들 모두에 대해
{
var processName = process.ProcessName;
if (processName.Equals("explorer")) // 프로세스 이름이 발견되면
{
var dd = process.MachineName;
sid = GetProcessInfoByPID(process.Id, out user);
}
}
public static string GetProcessInfoByPID(int PID, out string User)
{
User = String.Empty;
var OwnerSID = String.Empty;
string processname = String.Empty;
try
{
ObjectQuery sq = new ObjectQuery
("Select * from Win32_Process Where ProcessID = '" + PID + "'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(sq);
var searcherGet = searcher.Get();
if (searcherGet.Count == 0)
return OwnerSID;
foreach (ManagementObject oReturn in searcherGet)
{
string[] o = new String[2];
//시스템 계정 추출
oReturn.InvokeMethod("GetOwner", (object[])o);
User = o[0];
if (User == null)
User = String.Empty;
//시스템 SID 추출
string[] sid = new String[1];
oReturn.InvokeMethod("GetOwnerSid", (object[])sid);
OwnerSID = sid[0];
return OwnerSID;
}
}
catch
{
return OwnerSID;
}
return OwnerSID;
}
이제 시스템 계정의 SID까지 추출이 완료되었다. 이 SID로 레지스트리를 추출할 수 있다.
// 레지스트리 추출
var readPath = sid + "{RegistryPath}"; // 레지스트리 경로 입력
var ReadRegkey = Microsoft.Win32.Registry.Users.OpenSubKey(readPath);
return ReadRegkey?.GetValue("{Value}").ToString();
// 레지스트리 저장
var savePath = sid + "{RegistryPath}"; // 레지스트리 경로 입력
var saveRegKey = Microsoft.Win32.Users.OpenSubKey(savePath, true); // 레지스트리 경로 입력
if (!Microsoft.Win32.Users.GetSubKeyNames().Select(x => x.Equals(saveRegKey)).Any())
{
Microsoft.Win32.Users.CreateSubKey(saveRegKey);
}
saveRegKey?.SetValue("{key}", "{value}"); // 저장할 키와 값 입력
해당 샘플코드를 커스터마이징하여 사용하면 C#서비스 프로젝트에서 레지스트리 값을 조작할 경우나 다른 특별한 경우 프로세스가 시스템 계정이어도 정상적으로 현재 유저 계정의 레지스트리를 읽어올 수 있다.
댓글남기기