[
Advertise | Submit Code | About us | Contact us | Link us
]
Go!
Membership Services
Login
Register

Home
C# General

General

C# Language

Design & Architecture

Algorithms

Database

Security

Active Directory

COM Interop

Remoting
C# Windows Forms

General

Combo and List boxes

Miscellaneous Controls

Button Controls

Edit Controls
Cutting Edge

ASP.NET 2.0

Visual Studio 2005

Windows Longhorn

SQL Server 2005
C# Multimedia and GDI+

General

DirectX

GDI+

Audio
Internet & Web

General

Images and multimedia

Database

Utilities

Security

ASP.NET Controls

Design and Architecture

Webservices
.NET

General

Design & Architecture

Algorithms

Database

Security

Active Directory

COM Interop

Remoting

ADO.NET

XML.NET

Tools

Enterprise

IDE
Visual Basic .NET

VB.NET General

VB.NET Controls
General Reading

.NET Books Review

Product Showcase

Book Chapters

Business Design & Strategy
Community

Discuss

Job Board

Discussion

CodeXchange
DeveloperLand

Advertise

Submit Code

About us

Contact us

Link us
Miscellaneous

Favorite Links

Downloads

Programming Sites

Top Stories
Regular Expressions

E-Mail

Date/Time
Home > C# General > General
Using the Network Functions in C# (Part I - User Functions)
Posted by on Monday, September 19, 2005 (EST)

This article will focus on the Network functions within the Win32 API library associated with Network Management.

This article has been viewed: 10,507 times
Technology: General.

NetworkApp.zip (6.48 KB)
NetworkFunctions.zip (44.69 KB)

Contents

Introduction

Welcome to another "How-to" article in Visual C#.NET. This article will focus on the Network functions within the Win32 API library associated with Network Management. The first thing is to point out is that there are two ways to manage users using the .NET Framework, the first being the Active Directory method, as you will notice you need to have Active Directory Installed and if you were managing users on a small network or on a stand alone station Active Directory won't be install and it would be not worth installing it. Therefore the other method and focus of this article is using the Platform Invoke layer and the Network functions of the Win32 API library. In this article we will look at how to Add, Delete and Modify Users and Groups using C# and also how we can query User and Network information for a machine or network, we will look at the following functions

  • NetUserAdd
  • NetUserDel
  • NetUserGetInfo
  • NetUserSetInfo
  • NetUserChangePassword
  • NetUserEnum
  • NetUserGetLocalGroups

Top Go to Table of Contents

Getting Started

First of all as I'm sure most C# developers out there know we have to include the InteropServices namespace in our project to allow us to access functions from DLL's and this can be done using the following snippet of code:
using System.Runtime.InteropServices;

Once we have included the access we can now include the declarations of the DLL's we are going to use and the Structures (structs) associated with them. Each of the calls needed will be discussed under the headings relating to what they do.

Top Go to Table of Contents

Adding a User using C#

One of the most important operations within the Network functions is that of Adding Users to either a network or Computer. To Add a user via C# we will need to use the NetAddUser [^] function, using this function allows us to specify a machine to add the user to or we can leave that null an the User is added to the local machine. In the below code snippet we can see how we can declare and use the NetUserAdd function. One important item associated with the NetUserAdd function is that the user you are added must be in the form of a specific structure. The structures (structs) that are used in association with this call are USER INFO 1 [^], USER INFO 2 [^], USER INFO 3 [^] or USER INFO 4 [^]. In this practical example we shall use USER_INFO_1 to define our UserArea to add.

[DllImport("Netapi32.dll")]
extern static int NetUserAdd([MarshalAs(UnmanagedType.LPWStr)] string servername, 
 int level, 
 ref USER_INFO_1 buf, 
 int parm_err);
You should also note that when i used this code, i didn't need to know about the errors returned, hence the use of an int as the last parameter, if you did want to know about errors returned you would need to amend this code. Now that we have declared our external API to use we should also include our USER_INFO_1 structure, using the following code snippet:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct USER_INFO_1
{
 public string usri1_name; 
 public string usri1_password; 
 public int usri1_password_age; 
 public int usri1_priv; 
 public string usri1_home_dir; 
 public string comment; 
 public int usri1_flags; 
 public string usri1_script_path;
} 
Once we have both of these block of code declare we can now use the call from within our program, i should also note that in this case we have used the structure about you can use any of the other three, and if you click the link you can convert the code from C++ to C# pretty easily. Below is a code snippet to show the usage of the NetUserAdd function.

USER_INFO_1 NewUser = new USER_INFO_1(); // Create an new instance of the USER_INFO_1 struct
NewUser.usri1_name = "UserTestOne"; // Allocates the username
NewUser.usri1_password = "password"; // allocates the password
NewUser.usri1_priv = 1; // Sets the account type to USER_PRIV_USER
NewUser.usri1_home_dir = null; // We didn't supply a Home Directory
NewUser.comment = "My First User Made through C#"; // Comment on the User
NewUser.usri1_script_path = null; // We didn't supply a Logon Script Path
if(NetUserAdd(null ,1 ,ref NewUser, 0)!=0) // If the call fails we get a non-zero value
{
 MessageBox.Show("Error Adding User","Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
So as we discussed the above code will add a user to the machine you are currently on, but as I said if you want to add the user to a different machine on you network you can replace the first null parameter of the call with the name of the machine.

Top Go to Table of Contents

Removing a User using C#

Compared to the previous function removing a user is far easier, as with the above code the function returns a non-zero value if it fails, to remove a user from the local machine you can use the following declaration in the below code snippet.

[DllImport("Netapi32.dll")]
extern static int NetUserDel([MarshalAs(UnmanagedType.LPWStr)] string servername, 
 [MarshalAs(UnmanagedType.LPWStr)] string username);
The usage for the NetUserDel called would be as shown below in the code snippet.

if(NetUserDel(null ,"UserTestOne")!=0) // If the call fails we get a non-zero value
{
 MessageBox.Show("Error Removing User",
  "Error",
  MessageBoxButtons.OK,
  MessageBoxIcon.Error);
} 
As also with the NetUserAdd call, the user can make this call to remote machines by replacing the null string in the first parameter with that of the unicode representation or the computers name.

Top Go to Table of Contents

Getting User Information then modifying it using C#

To obtain user information within Visual C#.NET we need to used the native call NetUserGetInfo, this call as with NetUserAdd uses a structure (struct) to manage the data, however in this case it returns data to a struct as opposed to taking it out. In association with NetUserGetInfo, to change the information you have obtained you can use the function NetUserSetInfo. You should also note that these functions rely on each other to allow changes, for example to use the NetUserSetInfo function you must know the users privilege level, which is obtained via the NetUserGetInfo function. In the below code snippet we have the required declarations for both calls and please NOTE for this function we are using the USER_INFO_1 structure from above again.

[DllImport("Netapi32.dll")]
extern static int NetUserGetInfo([MarshalAs(UnmanagedType.LPWStr)] string servername,
 [MarshalAs(UnmanagedType.LPWStr)] string username,
 int level,
 out IntPtr bufptr);
[DllImport("Netapi32.dll")]
extern static int NetUserSetInfo([MarshalAs(UnmanagedType.LPWStr)] string servername,
 [MarshalAs(UnmanagedType.LPWStr)] string username,
 int level,
 ref USER_INFO_1 buf, 
 int error);
Using these declarations we can obtain and modify a users settings, with ease, if we look at the next code snippet we will obtain the user information for the user we made earlier "UserTestOne" and then we will change some user information.

// In this case we have used Marshaling to obtain the data this is the only method i found that
// work but im sure someone can correct me on that?
IntPtr bufPtr;
USER_INFO_1 User = new USER_INFO_1();
if(NetUserGetInfo(null, "Administrator",1,out bufPtr)!=0)
{
 MessageBox.Show("Error Getting User Info",
  "Error",
  MessageBoxButtons.OK,
  MessageBoxIcon.Error);
}
User = (USER_INFO_1)Marshal.PtrToStructure(bufPtr, typeof(USER_INFO_1)); 
MessageBox.Show("Users Name: " + 
 User.usri1_name + 
 " Users Comments: " + 
 User.comment + " 
 Users Privilege Level: " + 
 User.usri1_priv);

To summarize, NetUserSetInfo relies on NetUserGetInfo for it to work correctly, and as with all the other Network functions, if you change the null string in the first parameter to that of a computer, then you can use the function remotely.

Top Go to Table of Contents

Changing a Users Password using C#

Another very important function of a network management program is to allow the changing or passwords. The function NetUserChangePassword, allows us to do this bascially providing we have the user specified current password. So this function could be considered to be used as part of a program that allows a user to change their own password. Anyway to declare the NetUserChangePassword function we use the following code snippet.

[DllImport("Netapi32.dll")]
extern static int NetUserChangePassword([MarshalAs(UnmanagedType.LPWStr)] string domainname,
 [MarshalAs(UnmanagedType.LPWStr)] string username,
 [MarshalAs(UnmanagedType.LPWStr)] string oldpassword,
 [MarshalAs(UnmanagedType.LPWStr)] string newpassword);
Using this declaration we can now manipulate a set users password, providing we know it already. Again we can use the below code remotely changing the null string parameter to that of the machine to manage.

if(NetUserChangePassword(null, "UserTestOne", "password", "ournewpassword")!=0)
{
 MessageBox.Show("Error Changing User Password",
  "Error",
  MessageBoxButtons.OK,
  MessageBoxIcon.Error);
}

Top Go to Table of Contents

Obtaining the list of Users using C#

When managing a network it is also important what we have a accurate list of the users on the network, or local machine. To obtain this we must use the NetUserEnum function, which returns the names and data elements of each user area to structures. In this case we are going to use the USER_INFO_0 structure to pass the return values into, simply because we are only trying to get usernames no other data i have added this in the declarations section. It is also important to note that this function uses the network buffer, which must be freed after, to free resources, this is done using the NetAPIBufferFree function also listed. To start with in this code snippet is the declarations.

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct USER_INFO_0
{
public String Username;
}
[DllImport("Netapi32.dll")]
extern static int NetUserEnum([MarshalAs(UnmanagedType.LPWStr)] string servername, 
 int level, 
 int filter, 
 out IntPtr bufptr, 
 int prefmaxlen, 
 out int entriesread, 
 out int totalentries, 
 out int resume_handle);
[DllImport("Netapi32.dll")]
extern static int NetApiBufferFree(IntPtr Buffer);
Once we have made the declaration we can go out and use our code, to create the collection of the users, to do this we use the below code snippet.

int EntriesRead;
int TotalEntries;
int Resume;
IntPtr bufPtr;
NetUserEnum(null, 0, 2, out bufPtr, -1, out EntriesRead, out TotalEntries, out Resume);
if(EntriesRead> 0)
{
USER_INFO_0[] Users = new USER_INFO_0[EntriesRead];
IntPtr iter = bufPtr;
for(int i=0; i < EntriesRead; i++)
{
Users[i] = (USER_INFO_0)Marshal.PtrToStructure(iter, typeof(USER_INFO_0)); 
iter = (IntPtr)((int)iter + Marshal.SizeOf(typeof(USER_INFO_0)));
MessageBox.Show(Users[i].Username);
}
NetworkAPI.NetApiBufferFree(bufPtr);
}
The above code intern returns each use listed on the local machine via MessageBox, as with all other function you can chose a remote computer again by replacing the null string.

Top Go to Table of Contents

Identifying a users group membership using C#

The one last function we need to look at in this article is NetUserGetLocalGroups. This function allows us to determine what Groups the user is a member of and display them. As with the previous method we have to flush the NetAPIBuffer after using the function, using the same declaration as earlier. The declaration for NetUserGetLocalGroups also needs the LOCALGROUP_USERS_INFO_0 structure to return the names to this along with the declaration are shown in the below code snippet.

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct LOCALGROUP_USERS_INFO_0
{
public string groupname;
}
[DllImport("Netapi32.dll")]
public extern static int NetUserGetLocalGroups([MarshalAs(UnmanagedType.LPWStr)] string servername,
 [MarshalAs(UnmanagedType.LPWStr)] string username, 
 int level, 
 int flags, 
 out IntPtr bufptr, 
 int prefmaxlen, 
 out int entriesread, 
 out int totalentries);
With the above declaration we can now call it using similar code as in the previous functions, looking something like the below code snippet.

int EntriesRead;
int TotalEntries;
IntPtr bufPtr;
NetUserGetLocalGroups(null, "Administrator",0,0,out bufPtr,1024,out EntriesRead, out TotalEntries);
if(EntriesRead> 0)
{
LOCALGROUP_USERS_INFO_0[] RetGroups = new LOCALGROUP_USERS_INFO_0[EntriesRead];
IntPtr iter = bufPtr;
for(int i=0; i < EntriesRead; i++)
{
RetGroups[i] = (LOCALGROUP_USERS_INFO_0)Marshal.PtrToStructure(iter, typeof(LOCALGROUP_USERS_INFO_0)); 
iter = (IntPtr)((int)iter + Marshal.SizeOf(typeof(LOCALGROUP_USERS_INFO_0)));
MessageBox.Show(RetGroups[i].groupname);
}
 NetApiBufferFree(bufPtr);
}
The above example returns the groups to which the user Administrator belongs, again you can specify any user and any computer name. In this article we has looked at and discussed the User related Network Function available through Platform Invoke on the .NET Framework. So you can see that all this code does in fact work, i have included a sample Example application with all the function working in it. Available for download below.

Top Go to Table of Contents

About DeveloperLand Administrator

Click here if you want to know more about .

Other articles that may interest you

  • Write a Word Add-In – Part 0
  • Write a Word Add-In – Part I
  • Lengthy Operations on Single Thread in .NET Application
  • Learning Draughts
  • Exceptions and Performance
  • Average Rating :

    Discussion Forums
    Got a programming related question? Hopefully someone has the answer... Want to help out other developers? Visit our discussion forums.

    Sponsored by:

    New Articles

  • Exceptions and Performance
    Almost every time exceptions are mentioned in mailing lists and newsgroups, people say they're really expensive.Let's examine that claim, shall we?

  • Creating multilingual websites - Part 1
    Extend the existing globalization capabilities of .NET to create flexible and powerful multilingual web sites. First, create a custom ResourceManager, and then create custom localized-capable server controls to easily deploy multilingual functionality.

  • Parameter passing in C#
    Many people have become fairly confused about how parameters are passed in C#, particularly with regard to reference types. This page should help to clear up some of that confusion

  • Most Popular Articles

  • LDAP, IIS and WinNT Directory Services
    This article explains how to use .NET Directory Services to retrieve and search directory objects, create new directory objects and edit or delete existing directory objects. Describes Active Directory Application Mode (ADAM) and how to use the IIS, WinNT and LDAP directory (ADSI) provider.

  • An in-depth look at WMI and instrumentation, Part II
    WMI stands for Windows Management Instrumentation and, as the name indicates, is about managing your IT infrastructure this article is the second part of a two-part series.

  • An in-depth look at WMI and instrumentation, Part I
    WMI stands for Windows Management Instrumentation and, as the name indicates, is about managing your IT infrastructure this article provides an in-depth look at WMI and MOM 2005

  • New Books

  • Murach's ASP.NET 2.0 Upgrader's Guide: VB Edition
    What’s new and how to use it! That’s what this book delivers if you’re a VB developer who’s interested in upgrading from ASP.NET 1.x to ASP.NET 2.0.

  • C# in easy steps
    Learn to program with Microsoft’s premier programming language. No previous programming knowledge is assumed. With numerous easy-to-follow examples, this title explains the essentials of object-oriented programming with C#.

  • Murach's ASP.NET web programming with VB.NET
    Murach's ASP.NET web programming with VB.NET by Doug Lowe and Anne Prince is a in depth training and reference book for ASP.NET programming using VB.NET. The book builds upon Murach's previous books and covers more advanced concepts for programming ASP.NET pages.

  • Got Code?

    if you have any article , source code , or anything else you'd like to share with this community that you think others might find useful, please submit it here and we will gladly make it available on this site. submit@developerland.com.
    Partners

    All articles are copyrighted by their individual authors unless otherwise specified , everything else Copyright ©2004-2006 DeveloperLand