简体   繁体   English

在Windows中使用本地C#应用程序检查MaxPasswordAge

[英]Check MaxPasswordAge in Windows with local C# application

I am having the worst time trying to find documentation of this on the internet. 我遇到了最糟糕的时间,试图在互联网上找到有关此文档的信息。 Essentially I want to know that Secpol MaXPWAge is set to 90 or less and have it display in a textbox (let's call it textbox1 for ease) I have searched WMI solution, registry, GPEDIT in auditor and have found nothing. 从本质上讲,我想知道Secpol MaXPWAge设置为90或更低,并使其显示在文本框中(为方便起见,将其称为textbox1)我已经在审计程序中搜索了WMI解决方案,注册表,GPEDIT,却一无所获。 I did find this, but honestly, I have no clue how to use the same code to check the Max Password Age instead of complexity requirements. 我确实发现了这一点,但是老实说,我不知道如何使用相同的代码来检查“最大密码年龄”,而不是复杂性要求。 PLEASE, can someone show me what I should be doing here? 请有人能告诉我我应该在这里做什么? C# is not my primary language. C#不是我的主要语言。

https://gist.github.com/jkingry/421802 https://gist.github.com/jkingry/421802

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        Console.Write(PasswordComplexityPolicy());
    }

    static bool PasswordComplexityPolicy()
    {
        var tempFile = Path.GetTempFileName();

        Process p = new Process();
        p.StartInfo.FileName = Environment.ExpandEnvironmentVariables(@"%SystemRoot%\system32\secedit.exe");
        p.StartInfo.Arguments = String.Format(@"/export /cfg ""{0}"" /quiet", tempFile);
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.UseShellExecute = false;
        p.Start();
        p.WaitForExit();

        var file = IniFile.Load(tempFile);

        IniSection systemAccess = null;
        var passwordComplexityString = "";
        var passwordComplexity = 0;

        return file.Sections.TryGetValue("System Access", out systemAccess)
            && systemAccess.TryGetValue("PasswordComplexity", out passwordComplexityString)
            && Int32.TryParse(passwordComplexityString, out passwordComplexity)
            && passwordComplexity == 1;
    }

    class IniFile
    {
        public static IniFile Load(string filename)
        {
            var result = new IniFile();
            result.Sections = new Dictionary<string, IniSection>();
            var section = new IniSection(String.Empty);
            result.Sections.Add(section.Name, section);

            foreach (var line in File.ReadAllLines(filename))
            {
                var trimedLine = line.Trim();
                switch (line[0])
                {
                    case ';':
                        continue;
                    case '[':
                        section = new IniSection(trimedLine.Substring(1, trimedLine.Length - 2));
                        result.Sections.Add(section.Name, section);
                        break;
                    default:
                        var parts = trimedLine.Split('=');
                        if(parts.Length > 1)
                        {
                            section.Add(parts[0].Trim(), parts[1].Trim());
                        }
                        break;
                }                    
            }

            return result;
        }

        public IDictionary<string, IniSection> Sections { get; private set; }
    }

    class IniSection : Dictionary<string, string>
    {
        public IniSection(string name) : base(StringComparer.OrdinalIgnoreCase)
        {
            this.Name = name;
        }

        public string Name { get; private set; }
    }
}

This is kind of a cheat, but it works if you're only looking for that one thing. 这有点作弊,但是如果您只想找一件事,它就可以工作。 Basically it starts a new process and runs net accounts , then scapes the Maximum password age field from the output. 基本上,它开始一个新进程并运行net accounts ,然后从输出中选择Maximum password age字段。 Try it out, but you might have to run it as an administrator: 尝试一下,但是您可能必须以管理员身份运行它:

var process = new Process
{
    StartInfo = new ProcessStartInfo()
    {
        FileName = "net",
        Arguments = "accounts",
        UseShellExecute = false,
        RedirectStandardOutput = true,
        CreateNoWindow = true
    }
};

process.Start();
string text = "";
while (!process.StandardOutput.EndOfStream)
{
    text = process.StandardOutput.ReadLine();
    if (text != null && text.StartsWith("Maximum password age (days):"))
        break;
}
if (text == null || !text.StartsWith("Maximum password age (days):"))
    return;
text = text.Replace("Maximum password age (days):", "").Trim();

textBox1.Text = text;

I would write the IniFile class like this: 我会这样写IniFile类:

class IniFile : Dictionary<string,Dictionary<string,string>> {
    public IniFile(string filename) {
        var currentSection = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        Add("", currentSection);
        foreach (var line in File.ReadAllLines(filename)) {
            var trimedLine = line.Trim();
            switch (line[0]) {
                case ';':
                    continue;
                case '[':
                    currentSection = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
                    Add(trimedLine.Substring(1, trimedLine.Length - 2), currentSection);
                    break;
                default:
                    var parts = trimedLine.Split('=');
                    if (parts.Length > 1) {
                        currentSection.Add(parts[0].Trim(), parts[1].Trim());
                    }
                    break;
            }
        }
    }
    public string this[string sectionName, string key] {
        get {
            Dictionary<string, string> section;
            if (!TryGetValue(sectionName, out section)) { return null; }
            string value;
            if (!section.TryGetValue(key, out value)) { return null; }
            return value;
        }
    }
    public int? GetInt(string sectionName, string key) {
        string stringValue = this[sectionName, key];
        int result;
        if (!int.TryParse(stringValue, out result)) { return null; }
        return result;
    }
}

and put the ini file generation into a separate method: 并将ini文件生成放入单独的方法中:

class Program {
    static void GenerateSecEditOutput(out string tempFile) {
        tempFile = Path.GetTempFileName();
        var p = new Process {
            StartInfo = new ProcessStartInfo {
                FileName = Environment.ExpandEnvironmentVariables(@"%SystemRoot%\system32\secedit.exe"),
                Arguments = String.Format(@"/export /cfg ""{0}"" /quiet", tempFile),
                CreateNoWindow = true,
                UseShellExecute = false
            }
        };
        p.Start();
        p.WaitForExit();
    }

    //... Main goes here
}

Then, the Main method looks like this: 然后, Main方法如下所示:

static void Main(string[] args) {
    //This will be the path of the temporary file which contains the output of secedit.exe
    string tempFile;

    //Write the output of secedit.exe to the temporary file
    GenerateSecEditOutput(out tempFile);

    //Parse the temporary file
    var iniFile = new IniFile(tempFile);

    //Read the maximum password age from the "System Access" section
    var maxPasswordAge = iniFile.GetInt("System Access", "MaximumPasswordAge");
    if (maxPasswordAge.HasValue) {
        Console.WriteLine("MaxPasswordAge = {0}", maxPasswordAge);
    } else {
        Console.WriteLine("Unable to find MaximumPasswordAge");
    }
    Console.ReadKey(true);
}

If you have some textbox you want to put the value into, the steps are more or less the same. 如果您要输入一些文本框,则步骤大致相同。 We can avoid the integer parsing, and use the indexer of IniFile : 我们可以避免整数解析,而使用IniFile的索引器:

string tempFile;
GenerateSecEditOutput(out tempFile);
var iniFile = new IniFile(tempFile);
//assuming tb is a variable referring to a textbox
tb.Text = iniFile["System Access", "MaximumPasswordAge"];

Keep in mind that secedit.exe requires admin permissions to run. 请记住, secedit.exe需要管理员权限才能运行。 Without admin permissions, the code won't fail; 没有管理员权限,代码不会失败; the temporary file will simply be empty. 临时文件将只是空的。 See here for some suggestions on how to do this. 有关如何执行此操作的一些建议,请参见此处

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM