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岂不美哉

posted @ 2020-12-29 21:10  Zahad003  阅读(139)  评论(0编辑  收藏  举报