If you are messing with IIS in C# code, you can do quite a bit if you System.DirectoryServices and the DirectoryEntry object. This can be extended if you know the name of the items in a the DirectoryEntry’s property collection. You can get these as follows:
using System;
using System.Collections.Generic;
using System.DirectoryServices;
namespace FindIISLogWithCSharp
{
class Program
{
static void Main(string[] args)
{
List<string> AvailableProperties = new List<string>();
DirectoryEntry folderRoot = new DirectoryEntry("IIS://localhost/W3SVC");
PropertyCollection pc = folderRoot.Properties;
foreach (PropertyValueCollection p in pc)
{
AvailableProperties.Add(p.PropertyName);
}
// Sort alphabetically
AvailableProperties.Sort();
foreach (String prop in AvailableProperties)
{
Console.WriteLine(prop);
}
}
}
}
Of course, different DirectoryEntry objects can have different lists. However, this exact one created the following list on a Windows 2008 R2 64-bit Server with IIS installed and configured.
Found a quality development blog recently that had a post on a topic I have been interested in but haven’t got around to working on. The topic is publishing a project using Visual Studio.
I saw some alternate resumes for designers and I thought I would do an alternate resume for a developer. Make sure that if you use this, you are applying at a company that will appreciate it and not just throw the resume away.
namespace Resume {
public class Candidate {
public ContactInfo Info {
get { return new Person {FirstName = "Jared", LastName = "Barneck",
Street = "9110 Rigewood Place", City = "West Jordan",
State = "Utah", Zip = "84088", Email = "Rhyous@yahoo.com"}
}
}
public List<Experience> WorkHistory {
get { List<Experience> exp = new List<Experience>();
exp.Add(new Experience() { Start = "3/2012", End = "Present",
Company = "Caradigm",
Positions = new string [] { "Lead Software Developer"};
exp.Add(new Experience() { Start = "9/2004", End = "3/2012",
Company = "LANDesk",
Positions = new string [] { "Software Developer",
"Systems Analyst Developer", "Product Support Expert/Lead",
"Channel Support Manager"}};
exp.Add(new Experience() { Start = "1/2000", End = "9/2004",
Company = "Convergys – Nortel Networks Account",
Positions = new string [] { "Advanced Networking Trainer",
"Technical Lead", "Support Engineer"}};
return experience;
}
}
public List<Education> Education {
get { List<Education> edu = new List<Education>();
edu.Add(new Education() { Start = "8/1999", End = "8/2004"
College = "Brigham Young University",
Degree = "BA – Technical Writing"};
edu.Add(new Education() { Start = "9/2006", End = "4/2009"
College = "Brigham Young University",
Description = "Various Computer Science courses"};
return edu;
}
}
public List<String> Certifications {
get { List<String> cert = new List<String>();
cert.Add("Certified LANDesk Engineer");
cert.Add("Nortel Networks - Routers");
cert.Add("Nortel Networks – L3 Switches");
cert.Add("MSCE NT 4.0" };
return cert;
}
}
public List<String> Skills {
get { List<String> skills = new List<String>();
skills.Add("C#"); skills.Add("WPF"); skills.Add( "MVVM");
skills.Add("PHP"); skills.Add("MySQL"); skills.Add("Apache");
skills.Add("Shell Scripts"); skills.Add("Batch Files");
skills.Add("FreeBSD"); skills.Add("Linux"); skills.Add("Mono");
return skills;
}
}
}
}
Have you ever wanted to have a TextBox that requires data or specifically formatted data and you want to enforce this validation and display this to the user.
Well, I figured this out, with a great deal of pain, but hey, it works.
You can download this project in it’s entirety here:
I started with a new WPF Project in Visual Studio. Here is a general overview of the steps I took to make this example project happen.
MainWindow.xaml
Here, create a simple form to fill out using TextBlock and TextBox pairs in a Grid.
Configure the TextBox elements to use binding.
Configure the TextBox elements to use the appropriate Validation. (See the validation examples we will create below.)
Below the form you created in a StackPanel, add some TextBlock elements to display the Validation’s ErrorConent.
Bind each TextBlock element to the TextBox in the form they pertain to.
Bind the Visibility of each TextBlock to the Errors. (We will use the converter below to return Visible if there is ErrorContent and Collapsed if not.)
To this file we add a Person class and then create and instance of it and set it the instance as the DataContext.
using System;
using System.Windows;
using System.ComponentModel;
namespace WpfTextBoxValidation
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Person p = new Person();
MainGrid.DataContext = p;
}
}
public class Person
{
public String FirstName { get; set; }
public String LastName { get; set; }
public int Age { get; set; }
public String Phone { get; set; }
}
}
ErrorCollectionToVisibility.cs
This class is used to convert the Validation.Error collection to a Visibility.
There is a property Validation.HasError but for some reason it is not available to bind to. If it were, I would bind to it and use the built-in BooleanToVisibility converter. But since, I can’t, I used this ErrorCollectionToVisibility converter which simply returns Visible if there is at least one item in the collection or Collapse if the Collection is null or empty.
using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace WpfTextBoxValidation
{
class ErrorCollectionToVisibility : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ReadOnlyCollection<ValidationError> collection = value as ReadOnlyCollection<ValidationError>;
if (collection != null && collection.Count > 0)
return Visibility.Visible;
else
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return new object();
}
}
}
OverThirteenValidationRule.cs
Here we check if the value is greater than 13 and if not, we return the false ValidationResult.
using System;
using System.Windows.Controls;
namespace WpfTextBoxValidation
{
public class OverThirteenValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
if (value != null)
{
int age = 0;
try
{
age = Convert.ToInt32(value);
}
catch
{
return new ValidationResult(false, "You must be older than 13!");
}
if (age > 13)
return ValidationResult.ValidResult;
}
return new ValidationResult(false, "You must be older than 13!");
}
}
}
TextBoxNotEmptyValidationRule.cs
This validation just makes sure there is at least one character in a TextBlock.
using System;
using System.Windows.Controls;
namespace WpfTextBoxValidation
{
public class TextBoxNotEmptyValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
string str = value as string;
if (str != null)
{
if (str.Length > 0)
return ValidationResult.ValidResult;
}
return new ValidationResult(false, Message);
}
public String Message { get; set; }
}
}
You have now learned to bind to Validation.ErrorContent.
The simple array is a single-dimensional array. The idea of an array is to be a list of items. Lets give you two examples.
Example 1 – Single-dimensional array example with integers
This list of numbers is an array.
1, 2, 3, 4, 5
To create an array in C# with the above list of numbers you would use the following code:
int[] nums = new int[] { 1, 2, 3, 4, 5 };
The variable “nums” now holds all five number values. These can be accessed with bracket notation with an index starting at 0. That means that nums[0] would return the first item in the array, which is 1.
nums[4] would return 5. However, be aware that you cannot overstep your bounds. You only have nums[0] through nums[4] and if you try to access any index out of the range, such as nums[5] you will get an exception.
You can change any item in the array as well.
nums[1] = 100;
After running the above statement, your array now looks like this:
1, 100, 3, 4, 5
Example 2 – Single-dimensional array example with chars
The variable “alphas ” now holds all the listed character values. These can be accessed with bracket notation with an index starting at 0. That means that alphas[0] would return the first item in the array, which is A. alphas[2] would return B. alphas[11] would return f. However, be aware that you cannot overstep your bounds. You only have alphas[0] through alphas[11] and if you try to access any index out of the range, such as alphas[12] you will get an exception.
You can change any item in the array as well.
alphas[0] = '@';
After running the above statement, your character array now looks like this:
The variable “fruit” now holds all the listed string values. These can be accessed with bracket notation with an index starting at 0. That means that fruit[0] would return the first item in the array, which is “apple”. fruit[2] would return “banana”. fruit[5] would return “grapefruit”. However, be aware that you cannot overstep your bounds. You only have fruit[0] through fruit[5] and if you try to access any index out of the range, such as fruit[6] you will get an exception.
You can change any item in the array as well.
fruit[2] = "plantain'';
Before this statement, fruit[2] was assigned the string “banana”, but after running the above statement, it is assigned the string “plantain”. So now your character array now looks like this:
“apple”, “orange”, “plantain”, “peach”, “pear”
Arrays of Arrays in C#
There are different kinds of Arrays of . Lets discuss them as they are not the same.
multidimensional
jagged arrays.
With multidimensional arrays, the arrays are arrays of lists, but the lists themselves are not exactly formed into an official C# array object. Some might argue that these are not actually arrays but it that is all semantics.
With jagged arrays, the arrays are arrays of lists, and the lists themselves are also C# array objects.
Multidimensional Array in C#
A multi-dimensional array is an array of fixed size arrays and is often depicted at a table. Lets learn by some examples.
Two-dimensional array examples
First lest have three examples of two-dimensional arrays.
Example 1 – A multidimensional array of number pairs
The first digit inside the brackets, 6, indicates the number of groups. The second digit, 2, indicates the number of items in the group.
You can now access any of the numbers using the following syntax.
char val = alphaUpperAndLower[0,0];
The above will return the first item in the first pair, which is ‘A’. Or to get the second item in the last pair do this:
char val = alphaUpperAndLower[5,1];
However, because this is a multi-dimensional array, you cannot access the character pairs as an array. The following is NOT allowed.
char[] pair = alphaUpperAndLower[0];
That gives you a compile error. That is because the number pairs are not really stored in memory as C# array objects.
Three-dimensional array examples
We have already shown you some two-dimensional examples, now here are some three-dimensional examples.
Note: Of course, there is no limit to the number of dimensions you can create, but each dimension becomes exponentially more complex.
Example 4 – A three-dimensional array of numbers
Imagine you have the following groups of number groups, where the number groups are always three numbers, and there are always three groups.
{ 10, 11, 12 }, { 20, 21, 22 }, { 30, 31, 32 },
{ 40, 41, 42 }, { 50, 51, 52 } , { 60, 61, 62 },
{70, 71, 72 }, { 80, 81, 82 }, { 90, 91, 92 }
So if two-dimensional was displayed as a grid, you can assume that three-dimensional is displays similar to a cube. We have 3 groups of three groups of three numbers or 3x3x3, which is a cube.
The first digit inside the brackets, 3, indicates the number of groups of groups. The second digit, 2, indicates the number of groups of numbers, and the third digit indicates the count of numbers in the group.
You can now access any of the numbers using the following syntax.
int val = cube[0,0,0];
The above will return the first item in the first pair, which is 10. Or to get the last number in the last group of number in the last group of groups do this:
int val = cube[2,2,2];
However, because this is a multi-dimensional array, you cannot access the number groups or the groups of groups as arrays. The following two statements are NOT allowed.
That gives you a compile error. That is because the number pairs are not really stored in memory as C# array objects.
Jagged Array in C#
A jagged array is an array of variable-sized arrays. For example, imagine you have the following arrays of numbers and you want an array of these arrays.
int[][] jagged = new int[][] { new int[]{ 10, 11, 12 }, new int[]{ 20, 21, 22, 23, 24 },
new int[]{ 30, 31 }, new int[]{ 40, 41, 42, 43, 44, 45 },
new int[]{ 50, 51, 52 } };
Notice that you have to actually instantiate each individual array inside the jagged array.
You can now access any of the numbers using the following syntax.
int val = jagged[0][0];
The above will return the first item in the first pair, which is 10. Or to get the last number in the last group of number in the last group of groups do this:
int val = jagged[4][2];
And because this is an array of arrays, you CAN access the internal groups as arrays. The following statement is VALID.
The problem with Canvas is that when you click on it, you don’t actually get the click event to occur unless you have a background that is not white.
One trick if you want white is to use white -1 or #FFFFFE or possibly Transparent (unless the parent is not white). So no one can tell it isn’t white, because it is as close to white as can be without actually being white.
Now your click event can occur.
Also you need to make the Canvas focusable.
Example 1 – Getting a Canvas to take keyboard focus from a TextBox with a mouse click
As C# developers, many of us would prefer to write Android Apps in C# as well. Novell had promised us MonoDroid, but we were quite concerned as to whether MonoDroid would ever be released when Novell was dismantled.
However, Xamarin spawned from the ashes like a phoenix to restore the viability of MonoDroid, restoring our hopes to writing in C# for the Android platform.
Though I am hopeful that MonoDroid will become popular allowing C# to be a commonly used language for Android devices, there is still some question as to whether Xamarin and its MonoDroid product will survive.
Xamarin is a new company and needs to survive first. Its business is to sell MonoDroid, which is not open source, but is a proprietary product. Unfortunately, MonoDroid may cost too much, preventing adoption among app developers. Xamarin requires a customer base and a continual adoption rate if it is going to survive. If the company folds, what is going to happen to the library and the apps that use it?
Is Development with MonoDroid Free? Yes and No!
Yes and no.
Yes because anybody can use and develop with MonoDroid at no cost. It isn’t until you need to publish an app to the app store that you need to buy a license. You can use the MonoDroid trial for as long as you want. Here is a quote from the trial website. [2]
The evaluation version of Mono for Android does not expire, but enables development and testing against the Android Emulator only.
No, because you need to buy a license once either of the following become true:
You need to test your code directly on a real device and not just an emulated device
You are ready to publish an app to the app store
So what is the cost of MonoDroid? Depends on if you buy Professional, Enterprise, or Enterprise Priority. On the Xamarin store, the following table can be found. To see it you have to add MonoDroid to your cart and then click the “Show product comparison” link. [1]
Professional
Enterprise
Enterprise Priority
Deploy to your devices
Publish to app stores
Enterprise distribution
Priority support queue
Guaranteed response time
License expiration
Never
Never
Never
Update subscription
1 Year
1 Year
1 Year
License usage
Original User
Seat
Seat
Price (USD)
$399
$999
$2,499
These costs are very low for business or enterprise customers who have C# developers and want to write Android apps. The cost of training a C# developer to develop apps for Android in Java may be far greater than training them to develop apps for Android using C# and buying a MonoDroid license.
Is MonoDroid easy to set up?
Update
MonoDroid is not down to a one-click installer.
Here is the old method of Installing without the One-click Installer
MonoDroid is simple to set up. Xamarin has some simple steps that can be found on their web site. They have MonoDroid installation instructions for installing MonoDroid for use with any of three environments.
Visual Studio (Important! Visual Studio Express is not supported)
These are very easy steps to complete, and I won’t repeat the steps here, but once you complete them, you are ready to start writing Android apps in C#.
Once you feel you have everything installed, click the following link to continue reading.
I needed to determine if a class or one of its instances implements and interface. So I created this test project to see if this works.
Turns out it is really easy to do. Here is a test project that I used to learn. Just create a new console project and stick this code in the Program.cs and check it out.
namespace TestIfThisImplementsInterface
{
class Program
{
static void Main(string[] args)
{
// Test if the type or its parent implements the interface
bool bCarClass = typeof(IDrivable).IsAssignableFrom(typeof(Car)); // True
bool bFordFocusClass = typeof(IDrivable).IsAssignableFrom(typeof(FordFocus)); // True
bool bJunkerClass = typeof(IDrivable).IsAssignableFrom(typeof(Junker)); // False
// Test if the exact type and not its parent implements the derived type
bool bCarClassEx = typeof(Car).GetInterface(typeof(IDrivable).FullName) != null; // True
bool bFordFocusClassEx = typeof(Vehicle).GetInterface(typeof(IDrivable).FullName) != null; // False
bool bJunkerClassEx = typeof(Junker).GetInterface(typeof(IDrivable).FullName) != null; // True
// Test if an instance implements or derivces from an oject that implements the interface
bool bCarInstance = new Car() is IDrivable; // True
bool bFordFocusInstance = new FordFocus() is IDrivable; // True
bool bJunkerInstance = new Junker() is IDrivable; // False
// Test if an instance implements or derivces from an oject that implements the interface
bool bCarInstanceEx = new Car().GetType().GetInterface(typeof(IDrivable).FullName) != null; // True
bool bFordFocusInstanceEx = new FordFocus().GetType().GetInterface(typeof(IDrivable).FullName) != null; // False
bool bJunkerInstanceEx = new Junker().GetType().GetInterface(typeof(IDrivable).FullName) != null; // False
// Show that the test can be in the parent class but the actual class is what is tested
// This is actually what I needed. Glad it worked!
bool bCarParentFunction = new Car().IsDrivable; // True
bool bFordFocusParentFunction = new FordFocus().IsDrivable; // True
bool bJunkerParentFunction = new Junker().IsDrivable; // False
}
}
public interface IDrivable
{
void Drive();
}
public class Vehicle
{
public virtual bool IsDrivable
{
get { return this is IDrivable; }
}
}
public class Car : Vehicle, IDrivable
{
#region IDrivable Members
public void Drive()
{
// Drive code here
}
#endregion
}
public class FordFocus : Car
{
}
public class Junker : Vehicle
{
}
}
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.
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.
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:
// http://msdn.microsoft.com/en-us/library/system.management.managementscope%28v=VS.100%29.aspx
// 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();
}
}
}