How to authenticate and access the registry remotely using C#
Connecting to the remote registry of another workstation or server can be done as long as authentication has been done first.
Here is an example for connecting to remote registry.
- Create a new C# Console project in Visual Studio.
- Add a new class called NetworkShare. I know I got this from another site sometime last year and added to it, but I didn’t document the source web site.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
using
System;
using
System.Runtime.InteropServices;
using
BOOL = System.Int32;
namespace
NetworkConnection
{
public
class
NetworkShare
{
#region Member Variables
[DllImport(
"mpr.dll"
)]
private
static
extern
int
WNetAddConnection2A(
ref
NetResource refNetResource,
string
inPassword,
string
inUsername,
int
inFlags);
[DllImport(
"mpr.dll"
)]
private
static
extern
int
WNetCancelConnection2A(
string
inServer,
int
inFlags,
int
inForce);
private
String _Server;
private
String _Share;
private
String _DriveLetter =
null
;
private
String _Username =
null
;
private
String _Password =
null
;
private
int
_Flags = 0;
private
NetResource _NetResource =
new
NetResource();
BOOL _AllowDisconnectWhenInUse = 0;
// 0 = False; Any other value is True;
#endregion
#region Constructors
/// <summary>
/// The default constructor
/// </summary>
public
NetworkShare()
{
}
/// <summary>
/// This constructor takes a server and a share.
/// </summary>
public
NetworkShare(String inServer, String inShare)
{
_Server = inServer;
_Share = inShare;
}
/// <summary>
/// This constructor takes a server and a share and a local drive letter.
/// </summary>
public
NetworkShare(String inServer, String inShare, String inDriveLetter)
{
_Server = inServer;
_Share = inShare;
DriveLetter = inDriveLetter;
}
/// <summary>
/// This constructor takes a server, share, username, and password.
/// </summary>
public
NetworkShare(String inServer, String inShare, String inUsername, String inPassword)
{
_Server = inServer;
_Share = inShare;
_Username = inUsername;
_Password = inPassword;
}
/// <summary>
/// This constructor takes a server, share, drive letter, username, and password.
/// </summary>
public
NetworkShare(String inServer, String inShare, String inDriveLetter, String inUsername, String inPassword)
{
_Server = inServer;
_Share = inShare;
_DriveLetter = inDriveLetter;
_Username = inUsername;
_Password = inPassword;
}
#endregion
#region Properties
public
String Server
{
get
{
return
_Server; }
set
{ _Server = value; }
}
public
String Share
{
get
{
return
_Share; }
set
{ _Share = value; }
}
public
String FullPath
{
get
{
return
string
.Format(
@"\\{0}\{1}"
, _Server, _Share); }
}
public
String DriveLetter
{
get
{
return
_DriveLetter; }
set
{ SetDriveLetter(value); }
}
public
String Username
{
get
{
return
String.IsNullOrEmpty(_Username) ?
null
: _Username; }
set
{ _Username = value; }
}
public
String Password
{
get
{
return
String.IsNullOrEmpty(_Password) ?
null
: _Username; }
set
{ _Password = value; }
}
public
int
Flags
{
get
{
return
_Flags; }
set
{ _Flags = value; }
}
public
NetResource Resource
{
get
{
return
_NetResource; }
set
{ _NetResource = value; }
}
public
bool
AllowDisconnectWhenInUse
{
get
{
return
Convert.ToBoolean(_AllowDisconnectWhenInUse); }
set
{ _AllowDisconnectWhenInUse = Convert.ToInt32(value); }
}
#endregion
#region Functions
/// <summary>
/// Establishes a connection to the share.
///
/// Throws:
///
///
/// </summary>
public
int
Connect()
{
_NetResource.Scope = (
int
)Scope.RESOURCE_GLOBALNET;
_NetResource.Type = (
int
)Type.RESOURCETYPE_DISK;
_NetResource.DisplayType = (
int
)DisplayType.RESOURCEDISPLAYTYPE_SHARE;
_NetResource.Usage = (
int
)Usage.RESOURCEUSAGE_CONNECTABLE;
_NetResource.RemoteName = FullPath;
_NetResource.LocalName = DriveLetter;
return
WNetAddConnection2A(
ref
_NetResource, _Password, _Username, _Flags);
}
/// <summary>
/// Disconnects from the share.
/// </summary>
public
int
Disconnect()
{
int
retVal = 0;
if
(
null
!= _DriveLetter)
{
retVal = WNetCancelConnection2A(_DriveLetter, _Flags, _AllowDisconnectWhenInUse);
retVal = WNetCancelConnection2A(FullPath, _Flags, _AllowDisconnectWhenInUse);
}
else
{
retVal = WNetCancelConnection2A(FullPath, _Flags, _AllowDisconnectWhenInUse);
}
return
retVal;
}
private
void
SetDriveLetter(String inString)
{
if
(inString.Length == 1)
{
if
(
char
.IsLetter(inString.ToCharArray()[0]))
{
_DriveLetter = inString +
":"
;
}
else
{
// The character is not a drive letter
_DriveLetter =
null
;
}
}
else
if
(inString.Length == 2)
{
char
[] drive = inString.ToCharArray();
if
(
char
.IsLetter(drive[0]) && drive[1] ==
':'
)
{
_DriveLetter = inString;
}
else
{
// The character is not a drive letter
_DriveLetter =
null
;
}
}
else
{
// If we get here the value passed in is not valid
// so make it null.
_DriveLetter =
null
;
}
}
#endregion
#region NetResource Struct
[StructLayout(LayoutKind.Sequential)]
public
struct
NetResource
{
public
uint
Scope;
public
uint
Type;
public
uint
DisplayType;
public
uint
Usage;
public
string
LocalName;
public
string
RemoteName;
public
string
Comment;
public
string
Provider;
}
#endregion
#region Enums
public
enum
Scope
{
RESOURCE_CONNECTED = 1,
RESOURCE_GLOBALNET,
RESOURCE_REMEMBERED,
RESOURCE_RECENT,
RESOURCE_CONTEXT
}
public
enum
Type :
uint
{
RESOURCETYPE_ANY,
RESOURCETYPE_DISK,
RESOURCETYPE_PRINT,
RESOURCETYPE_RESERVED = 8,
RESOURCETYPE_UNKNOWN = 4294967295
}
public
enum
DisplayType
{
RESOURCEDISPLAYTYPE_GENERIC,
RESOURCEDISPLAYTYPE_DOMAIN,
RESOURCEDISPLAYTYPE_SERVER,
RESOURCEDISPLAYTYPE_SHARE,
RESOURCEDISPLAYTYPE_FILE,
RESOURCEDISPLAYTYPE_GROUP,
RESOURCEDISPLAYTYPE_NETWORK,
RESOURCEDISPLAYTYPE_ROOT,
RESOURCEDISPLAYTYPE_SHAREADMIN,
RESOURCEDISPLAYTYPE_DIRECTORY,
RESOURCEDISPLAYTYPE_TREE,
RESOURCEDISPLAYTYPE_NDSCONTAINER
}
public
enum
Usage :
uint
{
RESOURCEUSAGE_CONNECTABLE = 1,
RESOURCEUSAGE_CONTAINER = 2,
RESOURCEUSAGE_NOLOCALDEVICE = 4,
RESOURCEUSAGE_SIBLING = 8,
RESOURCEUSAGE_ATTACHED = 16,
RESOURCEUSAGE_ALL = 31,
RESOURCEUSAGE_RESERVED = 2147483648
}
public
enum
ConnectionFlags :
uint
{
CONNECT_UPDATE_PROFILE = 1,
CONNECT_UPDATE_RECENT = 2,
CONNECT_TEMPORARY = 4,
CONNECT_INTERACTIVE = 8,
CONNECT_PROMPT = 16,
CONNECT_NEED_DRIVE = 32,
CONNECT_REFCOUNT = 64,
CONNECT_REDIRECT = 128,
CONNECT_LOCALDRIVE = 256,
CONNECT_CURRENT_MEDIA = 512,
CONNECT_DEFERRED = 1024,
CONNECT_COMMANDLINE = 2048,
CONNECT_CMD_SAVECRED = 4096,
CONNECT_CRED_RESET = 8192,
CONNECT_RESERVED = 4278190080
}
#endregion
}
}
Note: This class actually is to map a drive, but authenticating to a share and authenticating to connect to remote registry are done the same way.
- Now here is a Program.cs that shows how to use the NetworkShare class to connect to a device and access the remote registry.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
using
System;
using
Microsoft.Win32;
using
NetworkConnection;
using
System.Management;
namespace
RemoteRegistryExample
{
class
Program
{
static
void
Main(
string
[] args)
{
String ServerName =
"Server1"
;
// Create an object that can authenticate to a network share when you
// already have credentials
NetworkShare share =
new
NetworkShare(ServerName,
"ipc$"
);
// Create an object that can authenticate to a network share when you
// do NOT already have credentials
//NetworkShare share = new NetworkShare(ServerName, "C$", "User", "SomePasswd");
// Connect to the remote drive
share.Connect();
// Note: another connection option is to add a reference to System.Management,
// Then add a using statement for System.Management and use ConnectionOptions
// and ManagementScope objects. For more information see this link:
// If these same credentials allow remote registry, you are now authenticated
// Get the Windows ProductName from HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
String ProductName =
string
.Empty;
RegistryKey key = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ServerName);
if
(key !=
null
)
{
key = key.OpenSubKey(
@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"
);
if
(key !=
null
)
ProductName = key.GetValue(
"ProductName"
).ToString();
}
// Display the value
Console.WriteLine(
"The device "
+ ServerName +
" is running "
+ ProductName +
"."
);
// Disconnect the share
share.Disconnect();
}
}
}
You now are reading from remote registry.