예제 #1
0
 public DistroProperties(int order, WslQueryDistroModel model)
 {
     Order         = order;
     WslDistroInfo = model ?? throw new ArgumentNullException(nameof(model));
     Properties    = GetDistroProperties(model);
     ImageKey      = SharedRoutines.GetImageKey(model?.DistroName);
 }
예제 #2
0
        public static CompilerResults CreateWslShim(string distroName, bool ignoreSwitches, string outputPath, string outputFileName)
        {
            var codeCompileUnit = new CodeCompileUnit();

            var targetNamespace = new CodeNamespace();

            var targetType = new CodeTypeDeclaration("Program")
            {
                IsClass = true,
                Attributes = MemberAttributes.Static | MemberAttributes.Private,
            };

            var mainMethod = new CodeMemberMethod()
            {
                Name = "Main",
                ReturnType = new CodeTypeReference(typeof(int)),
                Attributes = MemberAttributes.Static | MemberAttributes.Private,
                CustomAttributes = new CodeAttributeDeclarationCollection(new CodeAttributeDeclaration[]
                {
                    new CodeAttributeDeclaration(new CodeTypeReference(typeof(STAThreadAttribute))),
                }),
            };

            var argsMethodArgument = new CodeParameterDeclarationExpression(typeof(string[]), "args");
            mainMethod.Parameters.Add(argsMethodArgument);

            var declareDistroNameVariable = new CodeVariableDeclarationStatement(typeof(string), "distroName")
            {
                InitExpression = new CodePrimitiveExpression(distroName),
            };

            var declareWslPathVariable = new CodeVariableDeclarationStatement(typeof(string), "wslPath")
            {
                InitExpression = new CodeMethodInvokeExpression(
                    new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(typeof(Path)), nameof(Path.Combine)),
                    new CodeMethodInvokeExpression(
                        new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(typeof(Environment)), nameof(Environment.GetFolderPath)),
                        new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(typeof(Environment.SpecialFolder)), nameof(Environment.SpecialFolder.System))),
                    new CodePrimitiveExpression("wsl.exe")),
            };

            var declareStringListVariable = new CodeVariableDeclarationStatement(typeof(List<string>), "argsCandidate")
            {
                InitExpression = new CodeObjectCreateExpression(typeof(List<string>)),
            };

            var addPrependSwitchesStatement = new CodeMethodInvokeExpression(
                new CodeVariableReferenceExpression(declareStringListVariable.Name),
                nameof(List<string>.AddRange),
                new CodeArrayCreateExpression(
                    new CodeTypeReference(typeof(string[])),
                    new CodePrimitiveExpression("-d"),
                    new CodeVariableReferenceExpression(declareDistroNameVariable.Name))
                );

            CodeConditionStatement conditionStatement = null;

            if (!ignoreSwitches)
            {
                conditionStatement = new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("args"), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)));
                conditionStatement.TrueStatements.Add(new CodeMethodInvokeExpression(
                    new CodeVariableReferenceExpression(declareStringListVariable.Name),
                    nameof(List<string>.AddRange),
                    new CodeVariableReferenceExpression("args"))
                );
            }

            var declareWslArgsVariable = new CodeVariableDeclarationStatement(typeof(string), "wslArgs")
            {
                InitExpression = new CodeMethodInvokeExpression(
                    new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(typeof(string)), nameof(string.Join)),
                    new CodePrimitiveExpression(" "),
                    new CodeMethodInvokeExpression(new CodeVariableReferenceExpression(declareStringListVariable.Name), nameof(List<string>.ToArray))
                ),
            };

            var declareProcessStartInfoVariable = new CodeVariableDeclarationStatement(typeof(ProcessStartInfo), "psi")
            {
                InitExpression = new CodeObjectCreateExpression(
                    new CodeTypeReference(typeof(ProcessStartInfo)),
                        new CodeVariableReferenceExpression(declareWslPathVariable.Name),
                        new CodeVariableReferenceExpression(declareWslArgsVariable.Name)),
            };

            var assignPsiUseShellExecuteStatement = new CodeAssignStatement(
                new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(declareProcessStartInfoVariable.Name), nameof(ProcessStartInfo.UseShellExecute)),
                new CodePrimitiveExpression(false));

            var assignPsiCreateNoWindowStatement = new CodeAssignStatement(
                new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(declareProcessStartInfoVariable.Name), nameof(ProcessStartInfo.CreateNoWindow)),
                new CodePrimitiveExpression(false));

            var assignPsiRedirectStderrStatement = new CodeAssignStatement(
                new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(declareProcessStartInfoVariable.Name), nameof(ProcessStartInfo.RedirectStandardError)),
                new CodePrimitiveExpression(false));

            var assignPsiRedirectStdinStatement = new CodeAssignStatement(
                new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(declareProcessStartInfoVariable.Name), nameof(ProcessStartInfo.RedirectStandardInput)),
                new CodePrimitiveExpression(false));

            var assignPsiRedirectStdoutStatement = new CodeAssignStatement(
                new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(declareProcessStartInfoVariable.Name), nameof(ProcessStartInfo.RedirectStandardOutput)),
                new CodePrimitiveExpression(false));

            var assignPsiWindowStyleStatement = new CodeAssignStatement(
                new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(declareProcessStartInfoVariable.Name), nameof(ProcessStartInfo.WindowStyle)),
                new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(typeof(ProcessWindowStyle)), nameof(ProcessWindowStyle.Minimized)));

            var assignPsiWorkingDirectoryStatement = new CodeAssignStatement(
                new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(declareProcessStartInfoVariable.Name), nameof(ProcessStartInfo.WorkingDirectory)),
                new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(typeof(Environment)), nameof(Environment.CurrentDirectory)));

            var declareProcessVariable = new CodeVariableDeclarationStatement(new CodeTypeReference(typeof(Process)), "process")
            {
                InitExpression = new CodeObjectCreateExpression(new CodeTypeReference(typeof(Process))),
            };

            var assignProcessStartInfoStatement = new CodeAssignStatement(
                new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(declareProcessVariable.Name), nameof(Process.StartInfo)),
                new CodeVariableReferenceExpression(declareProcessStartInfoVariable.Name));

            var assignProcessEnableRaisingEventsStatement = new CodeAssignStatement(
                new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(declareProcessVariable.Name), nameof(Process.EnableRaisingEvents)),
                new CodePrimitiveExpression(true));

            var invokeProcessStartStatement = new CodeMethodInvokeExpression(
                new CodeVariableReferenceExpression(declareProcessVariable.Name),
                nameof(Process.Start));

            var invokeWaitForExitStatement = new CodeMethodInvokeExpression(
                new CodeVariableReferenceExpression(declareProcessVariable.Name),
                nameof(Process.WaitForExit));

            var declareExitCodeVariable = new CodeVariableDeclarationStatement(typeof(int), "exitCode")
            {
                InitExpression = new CodePropertyReferenceExpression(
                    new CodeVariableReferenceExpression(declareProcessVariable.Name),
                    nameof(Process.ExitCode)),
            };

            var assignExitCodeStatement = new CodeAssignStatement(
                new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(typeof(Environment)), nameof(Environment.ExitCode)),
                new CodeVariableReferenceExpression(declareExitCodeVariable.Name));

            var invokeDisposeStatement = new CodeMethodInvokeExpression(
                new CodeVariableReferenceExpression(declareProcessVariable.Name),
                nameof(Process.Dispose));

            var returnStatement = new CodeMethodReturnStatement(new CodeVariableReferenceExpression(declareExitCodeVariable.Name));

            mainMethod.Statements.Add(declareDistroNameVariable);
            mainMethod.Statements.Add(declareWslPathVariable);
            mainMethod.Statements.Add(declareStringListVariable);
            mainMethod.Statements.Add(addPrependSwitchesStatement);

            if (!ignoreSwitches)
                mainMethod.Statements.Add(conditionStatement);

            mainMethod.Statements.Add(declareWslArgsVariable);
            mainMethod.Statements.Add(declareProcessStartInfoVariable);
            mainMethod.Statements.Add(assignPsiUseShellExecuteStatement);
            mainMethod.Statements.Add(assignPsiCreateNoWindowStatement);
            mainMethod.Statements.Add(assignPsiRedirectStderrStatement);
            mainMethod.Statements.Add(assignPsiRedirectStdinStatement);
            mainMethod.Statements.Add(assignPsiRedirectStdoutStatement);
            mainMethod.Statements.Add(assignPsiWindowStyleStatement);
            mainMethod.Statements.Add(assignPsiWorkingDirectoryStatement);
            mainMethod.Statements.Add(declareProcessVariable);
            mainMethod.Statements.Add(assignProcessStartInfoStatement);
            mainMethod.Statements.Add(assignProcessEnableRaisingEventsStatement);
            mainMethod.Statements.Add(invokeProcessStartStatement);
            mainMethod.Statements.Add(invokeWaitForExitStatement);
            mainMethod.Statements.Add(declareExitCodeVariable);
            mainMethod.Statements.Add(assignExitCodeStatement);
            mainMethod.Statements.Add(returnStatement);

            targetType.Members.Add(mainMethod);
            targetNamespace.Types.Add(targetType);
            codeCompileUnit.Namespaces.Add(targetNamespace);

            var codeDomProvider = CodeDomProvider.CreateProvider("CSharp");
            var generatorOptions = new CodeGeneratorOptions()
            {
                BracingStyle = "C",
                BlankLinesBetweenMembers = false,
                ElseOnClosing = true,
            };

            var buffer = new StringBuilder();
            codeDomProvider.GenerateCodeFromCompileUnit(codeCompileUnit, new StringWriter(buffer), generatorOptions);

            var iconPath = Path.Combine(
                SharedRoutines.GetIconDirectoryPath(),
                SharedRoutines.GetImageKey(distroName) + ".ico");

            var iconCompilerOption = string.Empty;
            
            if (File.Exists(iconPath))
                iconCompilerOption = $@"/win32icon:""{iconPath}""";

            var compilerParameters = new CompilerParameters(new string[] { "System.dll", })
            {
                GenerateExecutable = true,
                GenerateInMemory = false,
                OutputAssembly = Path.Combine(outputPath, $"{outputFileName}.exe"),
                CompilerOptions = string.Join(" ", "/optimize+", iconCompilerOption),
            };

            return codeDomProvider.CompileAssemblyFromDom(compilerParameters, codeCompileUnit);
        }
예제 #3
0
 public DistroProperties(RegistryKey key)
 {
     this.Properties = SharedRoutines.GetDistroProperties(key);
     this.ImageKey   = SharedRoutines.GetImageKey(key);
 }