CSharp中的PInvoke
可以调用C/C++中的一些函数非常实用
Csharp中的数据类型
后面使用的时候可能会用到

PInvoke学习
简单例子
C++中我们可以使用 MessageBox()
函数来弹个窗,那么我们怎么在CSharp中调用这个函数呢
这下面是代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace ConsoleApp6
{
class Program
{
[DllImport("user32.dll")]
public static extern int MessageBox(int hWnd, String text, String caption, uint type);
static void Main(string[] args)
{
MessageBox(0,"Mikasa","Hello",0);
}
}
}

我们去微软的文档中看看这个函数的声明

首先这个是位于 User32.dll
因此我们会有一行代码是使用 DllImport
导入
函数定义如下
int MessageBox(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType
);
首先返回值是 int
,因此我们写成int,LPCTSTR是个字符串因此我们写成C#中的字符串,UINT在Csharp存在,HWND我们写成int(这个不知道为啥,按理说HWND是一个句柄,应该用CSharp中对应的IntPtr表示0.0)
参考至 https://www.pinvoke.net/search.aspx?search=MessageBox&namespace=user32

这个网站我们可以查到很多的函数、结构体等
Csharp添加用户
旧代码
以前使用 DirectoryEntry
来添加/删除用户的,代码如下
参考至: https://docs.microsoft.com/zh-cn/troubleshoot/dotnet/csharp/add-user-local-system
/*
Study By https://docs.microsoft.com/zh-cn/troubleshoot/dotnet/csharp/add-user-local-system
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
namespace NetUser
{
class Program
{
public static void AddUser(string username,string password)
{
try
{
DirectoryEntry AD = new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer");
DirectoryEntry NewUser = AD.Children.Add(username, "user");//Add User
NewUser.Invoke("SetPassword", new object[] { password });//Set Password
NewUser.Invoke("Put", new object[] { "Description", "Just For Record" });
NewUser.CommitChanges();
DirectoryEntry grp;
grp = AD.Children.Find("Administrators", "group");
if (grp != null) { grp.Invoke("Add", new object[] { NewUser.Path.ToString() }); }
Console.WriteLine("Account Create Successfully"); ;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public static void HeloMsg()
{
Console.WriteLine("Usage:NetUser.exe -a Saber Saber //AddUser");
Console.WriteLine("Usage:NetUser.exe -d Saber // DelUser");
}
public static void DelUser(string username)
{
try
{
DirectoryEntry AD = new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer");
DirectoryEntries ADD = AD.Children;
DirectoryEntry DelUser = ADD.Find(username,"user");
ADD.Remove(DelUser);
//AD.Children.Remove();
Console.WriteLine("Delete Success!");
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
static void Main(string[] args)
{
if (args.Contains("-a"))
{
AddUser(args[1],args[2]);
}
else if (args.Contains("-d"))
{
DelUser(args[1]);
}
else
{
HeloMsg();
}
}
}
}

在360/火绒全开的时候也是可以绕过的

新代码
之前学习过使用Windows的API添加用户,参考文章 https://www.cnblogs.com/17bdw/p/6790197.html
这里面我们试试能不能将他们改为CSharp的
Native.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace NetUserSomeThing
{
class Native
{
//定义USER_INFO_1结构体
public struct USER_INFO_1
{
[MarshalAs(UnmanagedType.LPWStr)]//设置为LPWStr类型
public string usri1_name;
public string usri1_password;
public uint usri1_password_age;
public uint usri1_priv;
public string usri1_home_dir;
public string usri1_comment;
public uint usri1_flags;
public string usri1_script_path;
}
[DllImport("netapi32.dll")]
public static extern int NetUserAdd(string servername,uint level,ref USER_INFO_1 userinfo,string parm_err);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct LOCALGROUP_MEMBERS_INFO_3
{
public string lgrmi3_domainandname;
}
[DllImport("netapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int NetLocalGroupAddMembers(string servername,string groupname,uint level,ref LOCALGROUP_MEMBERS_INFO_3 buf,uint totalentries);
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace NetUserSomeThing
{
class Native
{
//定义USER_INFO_1结构体
public struct USER_INFO_1
{
[MarshalAs(UnmanagedType.LPWStr)]//设置为LPWStr类型
public string usri1_name;
public string usri1_password;
public uint usri1_password_age;
public uint usri1_priv;
public string usri1_home_dir;
public string usri1_comment;
public uint usri1_flags;
public string usri1_script_path;
}
[DllImport("netapi32.dll")]
public static extern int NetUserAdd(string servername,uint level,ref USER_INFO_1 userinfo,string parm_err);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct LOCALGROUP_MEMBERS_INFO_3
{
public string lgrmi3_domainandname;
}
[DllImport("netapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int NetLocalGroupAddMembers(string servername,string groupname,uint level,ref LOCALGROUP_MEMBERS_INFO_3 buf,uint totalentries);
}
}

这次使用 PInvoke
的方法调用了C++的非托管代码实现使用Windows的API添加用户,说实话.NET框架真的有趣,C++也可以托管C#的代码(CS中的execute-Assem就是这个原理),下次有时间把这个完善一下,做一个只靠着WindowsApi实现 net user
命令的工具,试着加载到CS岂不美哉