winform实现软件注册的方法,注册表访问报错问题,Form.ShowDialog()窗体自动关闭问题

1,添加SoftRegister类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;

/*
 * 需要添加引用 System.Management
 */
namespace _033_软件注册01
{
    /// <summary>
    /// 软件注册类
    /// </summary>
    class SoftRegister
    {

        #region 第一步。根据卷标,CPU序列号,生成机器码
        
        ///<summary>
        /// 获取硬盘卷标号
        ///</summary>
        ///<returns></returns>
        public string GetDiskVolumeSerialNumber()
        {
            ManagementClass mc = new ManagementClass("win32_NetworkAdapterConfiguration");
            ManagementObject disk = new ManagementObject("win32_logicaldisk.deviceid=\"c:\"");
            disk.Get();
            return disk.GetPropertyValue("VolumeSerialNumber").ToString();
        }

        ///<summary>
        /// 获取CPU序列号
        ///</summary>
        ///<returns></returns>
        public string GetCpu()
        {
            string strCpu = null;
            ManagementClass myCpu = new ManagementClass("win32_Processor");
            ManagementObjectCollection myCpuCollection = myCpu.GetInstances();
            foreach (ManagementObject myObject in myCpuCollection)
            {
                strCpu = myObject.Properties["Processorid"].Value.ToString();
            }
            return strCpu;
        }

        ///<summary>
        /// 生成机器码(返回值:cpu序列号和硬盘序列号的前24位)
        ///</summary>
        ///<returns></returns>
        public string GetMNum()
        {
            string strNum = GetCpu() + GetDiskVolumeSerialNumber();
            string strMNum = strNum.Substring(0, 24); //截取前24位作为机器码
            return strMNum;
        }

        public int[] intCode = new int[127]; //存储密钥
        public char[] charCode = new char[25]; //存储ASCII码
        public int[] intNumber = new int[25]; //存储ASCII码值


        /// <summary>
        /// 初始化密钥
        /// </summary>
        public void SetIntCode()
        {
            for (int i = 1; i < intCode.Length; i++)
            {
                intCode[i] = i % 9;//0,1,2,3,4,5,6,7,8,0,1,2,3...
            }
        }

        #endregion

        #region 第二步。根据机器码 生成注册码 

        ///<summary>
        /// 根据机器码生成注册码
        ///</summary>
        ///<returns></returns>
        public string GetRNum()
        {
            SetIntCode();
            string strMNum = GetMNum();//获取机器码
            for (int i = 1; i < charCode.Length; i++) //存储机器码
            {
                charCode[i] = Convert.ToChar(strMNum.Substring(i - 1, 1));
            }
            for (int j = 1; j < intNumber.Length; j++) //改变ASCII码值
            {
                intNumber[j] = Convert.ToInt32(charCode[j]) + intCode[Convert.ToInt32(charCode[j])];
            }
            string strAsciiName = ""; //注册码
            for (int k = 1; k < intNumber.Length; k++) //生成注册码
            {

                if ((intNumber[k] >= 48 && intNumber[k] <= 57) || (intNumber[k] >= 65 && intNumber[k]
                                                                   <= 90) || (intNumber[k] >= 97 && intNumber[k] <= 122)) //判断如果在0-9、A-Z、a-z之间
                {
                    strAsciiName += Convert.ToChar(intNumber[k]).ToString();
                }
                else if (intNumber[k] > 122) //判断如果大于z
                {
                    strAsciiName += Convert.ToChar(intNumber[k] - 10).ToString();
                }
                else
                {
                    strAsciiName += Convert.ToChar(intNumber[k] - 9).ToString();
                }
            }
            return strAsciiName;
        }

        #endregion

    }
}

2,在主窗体Load事件添加

        private void MainFrm_Load(object sender, EventArgs e)
        {
            #region 软件注册 第三步。检查注册状况
            SoftRegister softReg = new SoftRegister();

            //判断软件是否注册
            RegistryKey retkey = Registry.CurrentUser.OpenSubKey("SOFTWARE", true).CreateSubKey("jason").CreateSubKey("jason.INI");
            //遍历所有子项的名称
            foreach (string strRNum in retkey.GetSubKeyNames())
            {
                if (strRNum == softReg.GetRNum())//检查注册表 来 对比 根据获取电脑信息运算的得到的注册码
                {
                    this.lbl_RegInfo.Text = "此软件已注册!";
                    this.btn_Register.Enabled = false;
                    return;
                }
            }
            this.Text = "此软件尚未注册!";
            this.btn_Register.Enabled = true;
            MessageBox.Show("您现在使用的是试用版,可以免费试用30次!", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
            Int32 tLong;//使用次数
            try
            {
                //检索与指定的注册表项中的指定名称关联的值。 如果在指定键未找到的名称,将返回你提供的默认值或null如果指定的键不存在。
                tLong = (Int32)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\jason", "UseTimes", 0);
                MessageBox.Show("您已经使用了" + tLong + "次!", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch
            {
                MessageBox.Show("欢迎使用本软件!", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
                Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\jason", "UseTimes", 0, RegistryValueKind.DWord);
            }
            //判断是否可以继续使用
            tLong = (Int32)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\jason", "UseTimes", 0);
            if (tLong < 30)
            {
                int tTimes = tLong + 1;
                Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\jason", "UseTimes", tTimes);
            }
            else
            {
                DialogResult result = MessageBox.Show("试用次数已到!您是否需要注册?", "信息", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
                if (result == DialogResult.Yes)
                {

                    RegisterFrm.state = false;
                    this.btn_Register_Click(sender, e);
                }
                else
                {
                    Application.Exit();
                }
            }
            #endregion

        }

3,在主窗体添加一个按钮和一个标签

注册按钮的代码:

        private void btn_Register_Click(object sender, EventArgs e)
        {
            RegisterFrm registerFrm = new RegisterFrm() { };
            //registerFrm.ShowDialog();//【特别注意】如果不加this,注册窗体会自动关闭
            registerFrm.ShowDialog(this);
        }

  

 4,补充:注册表访问报错问题

参考:https://www.cnblogs.com/Interkey/p/RunAsAdmin.html

解决1:修改程序文件的属性

右击程序文件,在弹出的属性对话框中的 兼容性 标签页中

勾选“以管理员身份运行此程序”即可。

解决2:通过 System.Diagnostics.Process.Start() 方式启动,这种方式无法调试运行了

修改默认生成的Program代码:

    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            //Application.Run(new FrmMain());

            #region 把Application.Run(new FrmMain());更改为以下
            
            /**
             * 当前用户是管理员的时候,直接启动应用程序
             * 如果不是管理员,则使用启动对象启动程序,以确保使用管理员身份运行
             */
            //获得当前登录的Windows用户标示
            System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent();
            System.Security.Principal.WindowsPrincipal principal = new System.Security.Principal.WindowsPrincipal(identity);
            //判断当前登录用户是否为管理员
            if (principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator))
            {
                //如果是管理员,则直接运行
                Application.Run(new FrmMain());
            }
            else
            {
                //创建启动对象
                System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
                startInfo.UseShellExecute = true;
                startInfo.WorkingDirectory = Environment.CurrentDirectory;
                startInfo.FileName = Application.ExecutablePath;
                //设置启动动作,确保以管理员身份运行
                startInfo.Verb = "runas";
                try
                {
                    System.Diagnostics.Process.Start(startInfo);//【注意】这种方式外部调用启动,所以无法加断点调试
                }
                catch
                {
                    return;
                }
                //退出
                Application.Exit();
            }
            #endregion

        }
    }

 

解决3:解决无法调试运行的问题

在 项目 上 添加新项 选择“应用程序清单文件” 然后单击 添加 按钮

添加后,默认打开app.manifest文件,将:

<requestedExecutionLevel  level="asInvoker" uiAccess="false" />

修改为:

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

然后打开 项目属性 ,将 应用程序 标签页中的 资源 中的 清单 修改为新建的 app.manifest。

重新生成项目,再次打开程序时就会提示 需要以管理员权限运行。

需要注意的是:如果在VS中 启动调试 的话,就会提示 此任务要求应用程序具有提升的权限。如下图:

选择 使用其他凭据重新启动 即可。

 

posted @ 2020-03-21 22:49  包子789654  阅读(408)  评论(0编辑  收藏  举报