Beispiel #1
0
            private static bool equalCommandLine(string commandLine, string[] args)
            {
                if (commandLine == null)
                {
                    return(false);
                }
                var argsLine = CommandRunner.ArgsToCommandLine(args);

                if (commandLine == argsLine)
                {
                    return(true);
                }
                var commands = WinAPI.CommandLineToArgs(commandLine);

                // first parameter is case-insensitive; the rest are case-sensitive
                return(args.Zip(commands, (a, c) => new { a, c }).Select((p, i) => i == 0 ? p.a.EqualsNoCase(p.c) : (p.a == p.c)).All(x => x));
            }
Beispiel #2
0
            /// <summary>
            ///     Starts a new instance of this process unconditionally (regardless of whether one is already running). See
            ///     also <see cref="SetRunning"/>. Verifies that the executable exists and logs an error if not. Pauses for a
            ///     configurable interval before starting the process to allow the script to be interrupted if desired (see
            ///     <see cref="WaitBeforeAction"/>). To verify that the process didn't exit a few seconds later, see <see
            ///     cref="Logmeon.CheckStarted"/>. Chainable.</summary>
            public Process Run()
            {
                var args = _startCommand ?? Args;

                if (!File.Exists(args[0]))
                {
                    WriteLineColored($"{{green}}{Name}{{}}: {{red}}file not found: {{}}{{yellow}}{args[0]}{{}}");
                    Logmeon.AnyFailures = true;
                    return(this);
                }
                WriteColored($"{{green}}{Name}{{}}: starting process in {_waitBeforeAction.TotalSeconds:0} seconds... ");
                Thread.Sleep(_waitBeforeAction);

                int processId;

                try
                {
                    var hToken        = IntPtr.Zero;
                    var pi            = new WinAPI.PROCESS_INFORMATION();
                    var hShellProcess = IntPtr.Zero;
                    var hShellToken   = IntPtr.Zero;
                    try
                    {
                        var si = new WinAPI.STARTUPINFO();
                        si.cb = Marshal.SizeOf(si);
                        var processAttributes = new WinAPI.SECURITY_ATTRIBUTES();
                        var threadAttributes  = new WinAPI.SECURITY_ATTRIBUTES();

                        if (_elevated)
                        {
                            WriteColored($"starting elevated... ");
                            if (!WinAPI.CreateProcess(null, CommandRunner.ArgsToCommandLine(args), ref processAttributes, ref threadAttributes, false, 0, IntPtr.Zero, WorkDir, ref si, out pi))
                            {
                                throw new Win32Exception();
                            }
                        }
                        else
                        {
                            WriteColored($"starting... ");
                            var shellWnd = WinAPI.GetShellWindow();
                            if (shellWnd == IntPtr.Zero)
                            {
                                throw new Exception("Could not find shell window");
                            }

                            uint shellProcessId;
                            WinAPI.GetWindowThreadProcessId(shellWnd, out shellProcessId);

                            hShellProcess = WinAPI.OpenProcess(0x00000400 /* QueryInformation */, false, shellProcessId);

                            if (!WinAPI.OpenProcessToken(hShellProcess, 2 /* TOKEN_DUPLICATE */, out hShellToken))
                            {
                                throw new Win32Exception();
                            }

                            uint tokenAccess = 8 /*TOKEN_QUERY*/ | 1 /*TOKEN_ASSIGN_PRIMARY*/ | 2 /*TOKEN_DUPLICATE*/ | 0x80 /*TOKEN_ADJUST_DEFAULT*/ | 0x100 /*TOKEN_ADJUST_SESSIONID*/;
                            WinAPI.DuplicateTokenEx(hShellToken, tokenAccess, IntPtr.Zero, 2 /* SecurityImpersonation */, 1 /* TokenPrimary */, out hToken);

                            if (!WinAPI.CreateProcessWithTokenW(hToken, 0, null, CommandRunner.ArgsToCommandLine(args), 0, IntPtr.Zero, WorkDir, ref si, out pi))
                            {
                                throw new Win32Exception();
                            }
                        }
                        processId = pi.dwProcessId;
                    }
                    finally
                    {
                        if (hToken != IntPtr.Zero && !WinAPI.CloseHandle(hToken))
                        {
                            throw new Win32Exception();
                        }
                        if (hShellToken != IntPtr.Zero && !WinAPI.CloseHandle(hShellToken))
                        {
                            throw new Win32Exception();
                        }
                        if (hShellProcess != IntPtr.Zero && !WinAPI.CloseHandle(hShellProcess))
                        {
                            throw new Win32Exception();
                        }
                        if (pi.hProcess != IntPtr.Zero && !WinAPI.CloseHandle(pi.hProcess))
                        {
                            throw new Win32Exception();
                        }
                        if (pi.hThread != IntPtr.Zero && !WinAPI.CloseHandle(pi.hThread))
                        {
                            throw new Win32Exception();
                        }
                    }
                }
                catch (Exception e)
                {
                    WriteLineColored($"{{green}}{Name}{{}}: {{red}}ERROR while starting process: {e.Message}{{}}");
                    AnyFailures = true;
                    return(this);
                }

                WriteLineColored($"done, ID={processId}.");
                _startedProcesses.Add(this);
                StartedAt = DateTime.UtcNow;
                return(this);
            }
Beispiel #3
0
        static int Main(string[] args)
        {
            try { Console.OutputEncoding = Encoding.UTF8; }
            catch { }

            if (args.Length == 2 && args[0] == "--post-build-check")
            {
                return(Ut.RunPostBuildChecks(args[1], typeof(Program).Assembly, typeof(Ut).Assembly));
            }

            CommandLine cmd;

            try
            {
                cmd = CommandLineParser.Parse <CommandLine>(args);
            }
            catch (CommandLineParseException pe)
            {
                pe.WriteUsageInfoToConsole();
                return(1);
            }

            string extraCode = null;

            if (cmd.ExtraCodeFile != null)
            {
                extraCode = File.ReadAllText(cmd.ExtraCodeFile);
            }

            var gp = cmd.GetGraphicsPath();

            Ut.Assert(gp.PathTypes.Length == gp.PathPoints.Length);
            var data = gp.PathTypes.Zip(gp.PathPoints, (pt, pp) => new { Type = (PathPointType)pt, Point = pp }).ToArray();

            Ut.Assert(data.Length > 0 && data[0].Type == PathPointType.Start);
            for (int i = 0; i < data.Length; i++)
            {
                if (data[i].Type == PathPointType.Start)
                {
                    Ut.Assert(i == 0 || data[i - 1].Type.HasFlag(PathPointType.CloseSubpath));
                }
                if (data[i].Type.HasFlag(PathPointType.CloseSubpath))
                {
                    Ut.Assert(i == data.Length - 1 || data[i + 1].Type == PathPointType.Start);
                }
            }

            var start  = data.CreateGenerex(inf => inf.Type == PathPointType.Start);
            var line   = data.CreateGenerex(inf => (inf.Type & PathPointType.PathTypeMask) == PathPointType.Line);
            var bézier = data.CreateGenerex(inf => (inf.Type & PathPointType.PathTypeMask) == PathPointType.Bezier3);
            var end    = data.CreateGenerex(inf => inf.Type.HasFlag(PathPointType.CloseSubpath));

            var regex = start.Process(m => m.Match[0].Point).ThenRaw(
                Generex.Ors(
                    line.Process(m => SegmentType.Line),
                    bézier.Times(3).Process(m => SegmentType.Bézier)
                    )
                .Process(m => new { Type = m.Result, Points = m.Match.Select(inf => inf.Point).ToArray() })
                .Repeat()
                .Then(end.LookBehind())
                .Do(m => m.Match.SkipLast(1).All(inf => !inf.Type.HasFlag(PathPointType.CloseSubpath))),
                (startPoint, segment) => new { StartPoint = startPoint, Segment = segment }
                ).RepeatGreedy();

            var match = regex.MatchExact(data);

            if (match == null)
            {
                throw new InvalidOperationException("The GraphicsPath data has not been recognized by Generex. This indicates a bug in the Generex grammar.");
            }

            var curves = match.Result.ToArray();

            var getPoints = Ut.Lambda((bool close) => curves.Select(curve =>
            {
                var segments = curve.Segment.Concat(new { Type = SegmentType.Line, Points = new[] { curve.StartPoint } });
                if (close)
                {
                    segments = segments.Concat(curve.Segment.First());
                }
                return(segments.Aggregate(
                           new { LastPoint = curve.StartPoint, Points = Enumerable.Empty <PointF>() },
                           (prev, next) =>
                           next.Type == SegmentType.Line && next.Points[0] == prev.LastPoint ? prev :
                           new
                {
                    LastPoint = next.Points.Last(),
                    Points = prev.Points.Concat(next.Type == SegmentType.Bézier
                                ? prev.LastPoint.Concat(next.Points)
                                : new[] { prev.LastPoint, new PointF(prev.LastPoint.X * 2 / 3 + next.Points[0].X * 1 / 3, prev.LastPoint.Y * 2 / 3 + next.Points[0].Y * 1 / 3), new PointF(prev.LastPoint.X * 1 / 3 + next.Points[0].X * 2 / 3, prev.LastPoint.Y * 1 / 3 + next.Points[0].Y * 2 / 3), next.Points[0] }
                                                )
                }
                           ).Points.ToArray());
            }).ToArray());
            var openPoints   = getPoints(false);
            var closedPoints = getPoints(true);

            var source = @"
// Command line:
// {4}{5}

#declare {3} = union {{
    prism {{
        bezier_spline linear_sweep 0, {0}, {1}
        {2}
        rotate 90*x
        {6}
    }}".Fmt(
                /* {0} */ cmd.ExtrusionDepth,
                /* {1} */ openPoints.Sum(p => p.Length),
                /* {2} */ openPoints.SelectMany(p => p).Split(4)
                .Select(grp => grp.Select(p => "<{0}, {1}>".Fmt(p.X, p.Y)).JoinString(", "))
                .JoinString("," + Environment.NewLine)
                .Indent(8, false),
                /* {3} */ cmd.ObjectName,
                /* {4} */ CommandRunner.ArgsToCommandLine(args),
                /* {5} */ cmd.ExtraCodeFile == null ? null : "\n// Extra code file:\n" + File.ReadAllLines(cmd.ExtraCodeFile).JoinString("\n", prefix: "// "),
                /* {6} */ extraCode
                );

            source += openPoints.SelectMany(gr => gr.Split(4).Select(Enumerable.ToArray).ConsecutivePairs(true)).Select(pair =>
            {
                var pts  = pair.Item1;
                var next = pair.Item2;

                var displaced     = displace(pts, cmd.RoundingRadius);
                var displacedNext = displace(next, cmd.RoundingRadius);

                var code = "";

                if (!cmd.SkipFront)
                {
                    code += patch(
                        "Front fillet",
                        Enumerable.Range(0, 4).Select(i => pts[i]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, 0)).JoinString(", "),
                        Enumerable.Range(0, 4).Select(i => combine(pts[i], displaced[i], cmd.RoundingFactor)).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, 0)).JoinString(", "),
                        Enumerable.Range(0, 4).Select(i => displaced[i]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, (-cmd.RoundingRadius) * (1 - cmd.RoundingFactor))).JoinString(", "),
                        Enumerable.Range(0, 4).Select(i => displaced[i]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, (-cmd.RoundingRadius))).JoinString(", "),
                        extraCode, cmd.Smoothness);
                }

                code += patch(
                    "Side",
                    displaced.Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, -cmd.RoundingRadius)).JoinString(", "),
                    displaced.Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, -cmd.RoundingRadius * 1 / 3 - cmd.ExtrusionDepth * 1 / 3)).JoinString(", "),
                    displaced.Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, cmd.RoundingRadius * 1 / 3 - cmd.ExtrusionDepth * 2 / 3)).JoinString(", "),
                    displaced.Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, cmd.RoundingRadius - cmd.ExtrusionDepth)).JoinString(", "),
                    extraCode, cmd.Smoothness);

                if (!cmd.SkipBack)
                {
                    code += patch(
                        "Back fillet",
                        Enumerable.Range(0, 4).Select(i => displaced[i]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, cmd.RoundingRadius - cmd.ExtrusionDepth)).JoinString(", "),
                        Enumerable.Range(0, 4).Select(i => displaced[i]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, combine(cmd.RoundingRadius - cmd.ExtrusionDepth, -cmd.ExtrusionDepth, cmd.RoundingFactor))).JoinString(", "),
                        Enumerable.Range(0, 4).Select(i => combine(pts[i], displaced[i], cmd.RoundingFactor)).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, -cmd.ExtrusionDepth)).JoinString(", "),
                        Enumerable.Range(0, 4).Select(i => pts[i]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, -cmd.ExtrusionDepth)).JoinString(", "),
                        extraCode, cmd.Smoothness);
                }

                Ut.Assert(pts[3] == next[0]);

                var angle1     = Math.Atan2(pts[3].Y - pts[2].Y, pts[3].X - pts[2].X);
                var angle2     = Math.Atan2(next[0].Y - next[1].Y, next[0].X - next[1].X);
                var totalAngle = angle1 - angle2;
                if (totalAngle < 0)
                {
                    totalAngle += Math.PI * 2;
                }
                if (totalAngle >= Math.PI)
                {
                    return(code);
                }

                var intersection = intersect(displaced[2], displaced[3], displacedNext[1], displacedNext[0]);
                if (float.IsNaN(intersection.X))
                {
                    return(code);
                }

                var fillet = Ut.NewArray(
                    displaced[3],
                    combine(displaced[3], intersection, cmd.RoundingFactor),
                    combine(displacedNext[0], intersection, cmd.RoundingFactor),
                    displacedNext[0]
                    );

                if (!cmd.SkipFront)
                {
                    code += patch(
                        "Front corner fillet",
                        Enumerable.Range(0, 4).Select(i => next[0]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, 0)).JoinString(", "),
                        Enumerable.Range(0, 4).Select(i => combine(next[0], fillet[i], cmd.RoundingFactor)).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, 0)).JoinString(", "),
                        Enumerable.Range(0, 4).Select(i => fillet[i]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, -cmd.RoundingRadius * (1 - cmd.RoundingFactor))).JoinString(", "),
                        Enumerable.Range(0, 4).Select(i => fillet[i]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, -cmd.RoundingRadius)).JoinString(", "),
                        extraCode, cmd.Smoothness);
                }

                code += patch(
                    "Side corner fillet",
                    Enumerable.Range(0, 4).Select(i => fillet[i]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, -cmd.RoundingRadius)).JoinString(", "),
                    Enumerable.Range(0, 4).Select(i => fillet[i]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, combine(-cmd.RoundingRadius, cmd.RoundingRadius - cmd.ExtrusionDepth, 1f / 3f))).JoinString(", "),
                    Enumerable.Range(0, 4).Select(i => fillet[i]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, combine(-cmd.RoundingRadius, cmd.RoundingRadius - cmd.ExtrusionDepth, 2f / 3f))).JoinString(", "),
                    Enumerable.Range(0, 4).Select(i => fillet[i]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, cmd.RoundingRadius - cmd.ExtrusionDepth)).JoinString(", "),
                    extraCode, cmd.Smoothness);

                if (!cmd.SkipBack)
                {
                    code += patch(
                        "Back corner fillet",
                        Enumerable.Range(0, 4).Select(i => fillet[i]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, cmd.RoundingRadius - cmd.ExtrusionDepth)).JoinString(", "),
                        Enumerable.Range(0, 4).Select(i => fillet[i]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, combine(cmd.RoundingRadius - cmd.ExtrusionDepth, -cmd.ExtrusionDepth, cmd.RoundingFactor))).JoinString(", "),
                        Enumerable.Range(0, 4).Select(i => combine(next[0], fillet[i], cmd.RoundingFactor)).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, -cmd.ExtrusionDepth)).JoinString(", "),
                        Enumerable.Range(0, 4).Select(i => next[0]).Select(p => "<{0}, {1}, {2}>".Fmt(p.X, p.Y, -cmd.ExtrusionDepth)).JoinString(", "),
                        extraCode, cmd.Smoothness);
                }

                return(code);
            }).JoinString(Environment.NewLine);

            source += Environment.NewLine + "}" + Environment.NewLine;

            File.WriteAllText(cmd.Filename, source);

            return(0);
        }