Exemplo n.º 1
0
        private void PrintSequentiallyLaidOutField(PrintContext context, int index, ref int currentOffset)
        {
            Debug.Assert(!isExplicitLayout);

            // sequential layout - no unions should be needed; however if the size
            // is "odd", we are in pragma pack (1) and the packing will be simulated
            // by our artificial padding fields
            if (!unalignedSizeOrOffsets)
            {
                context.SetPack(this.pack);
            }

            NativeField nf = fields[index];

            int previous_offset = currentOffset;

            AlignField(nf, ref currentOffset, true);

            if (unalignedSizeOrOffsets)
            {
                // inject artificial padding
                context.PrintPadding(currentOffset - previous_offset);
            }

            context.Printer.PrintLn();
            nf.PrintTo(context.Printer, context.LogPrinter, context.Flags);

            currentOffset += nf.Type.TypeSize;
        }
Exemplo n.º 2
0
        private void AlignField(NativeField field, ref int offset, bool updateOffset)
        {
            // - alignment-requirement of a struct field is the smaller of the declared packsize and the
            //   largest of the alignment-requirement of its fields
            // - alignment-requirement of a scalar field is the smaller of its size and the declared packsize
            int pack_requirement = Math.Min(field.Type.AlignmentRequirement, this.pack);

            // update the max field alignment requirement of this structure
            if (pack_requirement > this.maxFieldAlignmentReq)
            {
                this.maxFieldAlignmentReq = pack_requirement;
            }

            // advance the offset to satisfy the pack requirement
            if (updateOffset && pack_requirement > 0)
            {
                int mod = (offset % pack_requirement);
                if (mod > 0)
                {
                    offset += (pack_requirement - mod);
                }

                Debug.Assert(offset % pack_requirement == 0);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Determines whether we need to print pragma pack when we're padding up to the given offset.
        /// </summary>
        private bool IsPragmaPack1Needed(int offset, int @base)
        {
            for (int i = 0; i < fields.Length; i++)
            {
                NativeField nf = fields[i];
                if (nf.Offset.HasValue && nf.Offset.Value == offset)
                {
                    int tmp_offset = offset - @base;
                    AlignField(nf, ref tmp_offset, true);

                    if (tmp_offset != (offset - @base))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemplo n.º 4
0
        static void ProcessRecord
        (
            int mfn
        )
        {
            irbis.ReadRecord(mfn);
            NativeRecord record = irbis.GetRecord();
            NativeField  v933   = record.GetFirstField(933);

            if (ReferenceEquals(v933, null))
            {
                return;
            }

            string index = v933.Value;
            string description;

            if (!magazines.ContainsKey(index))
            {
                int[] found = irbis.ExactSearch("I=" + index);
                if (found.Length == 0)
                {
                    return;
                }
                description = irbis.FormatRecord(found[0]);
                magazines.Add(index, description);
            }
            description = magazines[index];

            NativeField v999  = record.GetFirstField(999);
            int         count = ReferenceEquals(v999, null)
                ? 0
                : v999.Value.SafeToInt32();

            Console.WriteLine
            (
                "{0}: {1}",
                irbis.FormatRecord(mfn),
                count
            );

            counter.Augment(description, count);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Sets up the <see cref="isUnion"/> and <see cref="unalignedSizeOrOffsets"/>
        /// </summary>
        private void SetupIsUnionFlag()
        {
            if (isExplicitLayout && fields.Length > 0)
            {
                NativeField nf = fields[0];
                if (!nf.Offset.HasValue || nf.Offset.Value > 0)
                {
                    // not having the first field at offset 0 disqualifies us from being a union
                    isUnion = false;
                    return;
                }

                int union_end;
                int end_index = ComputeLastUnitedField(0, out union_end);
                if (end_index != fields.Length - 1)
                {
                    // not grouping all fields into a union disqualifies us from being a union
                    isUnion = false;

                    // go through all fields now to set the unalignedSizeOrOffsets flag
                    do
                    {
                        end_index = ComputeLastUnitedField(end_index + 1, out union_end);
                    }while (end_index != fields.Length - 1);

                    return;
                }

                if (union_end != size)
                {
                    // not having the union as big as the desired size may be a problem
                    isUnion = false;
                    return;
                }

                isUnion = true;
            }
            else
            {
                isUnion = false;
            }
        }
Exemplo n.º 6
0
        private void PrintUnionField(PrintContext context, int fieldIndex, int unionOffset)
        {
            NativeField nf = fields[fieldIndex];

            if (nf.Offset.Value == unionOffset)
            {
                // no padding necessary - print the field
                context.Printer.PrintLn();
                nf.PrintTo(context.Printer, context.LogPrinter, context.Flags);
            }
            else
            {
                // this field will be wrapped in a struct with a padding before it
                if (IsPragmaPack1Needed(nf.Offset.Value, unionOffset))
                {
                    context.SetPack(1);
                }

                context.Printer.PrintLn();

                context.Printer.PrintLn(OutputType.Keyword, "struct");
                context.Printer.Print(OutputType.Operator, "{");

                context.Printer.Indent();
                try
                {
                    // add padding
                    context.PrintPadding(nf.Offset.Value - unionOffset);
                    context.Printer.PrintLn();

                    // add the field itself
                    nf.PrintTo(context.Printer, context.LogPrinter, context.Flags);
                }
                finally
                {
                    context.Printer.Unindent();

                    context.Printer.PrintLn();
                    context.Printer.Print(OutputType.Operator, "};");
                }
            }
        }
Exemplo n.º 7
0
        private void PrintExplicitlyLaidOutField(PrintContext context, ref int index, ref int currentOffset)
        {
            Debug.Assert(isExplicitLayout);

            NativeField nf = fields[index];

            int start = (nf.Offset ?? currentOffset);

            Debug.Assert(start >= currentOffset); // otherwise we would have printed it before

            bool pack1 = false;

            if (start > currentOffset)
            {
                if (IsPragmaPack1Needed(start))
                {
                    context.SetPack(1);
                    pack1 = true;
                }

                // there is a gap between the end of last field and start of this field
                context.PrintPadding(start - currentOffset);

                currentOffset = start;
            }

            if (!pack1 && !unalignedSizeOrOffsets)
            {
                context.SetPack(DefaultPack);
            }

            // determine the fields that will have to be grouped in a union
            int union_end;
            int last_united_index = ComputeLastUnitedField(index, out union_end);

            if (last_united_index > index)
            {
                context.Printer.PrintLn();
                context.Printer.Print(OutputType.Keyword, "union");

                if (isUnion)
                {
                    PrintIdentifierAndSize(context);
                }
                else
                {
                    context.Printer.PrintLn();
                }

                context.Printer.Print(OutputType.Operator, "{");

                context.Printer.Indent();
                try
                {
                    for (int j = index; j <= last_united_index; j++)
                    {
                        // the union field will be the field itself or an anonymous
                        // structure if a padding is needed to reach the field offset
                        PrintUnionField(context, j, currentOffset);
                    }
                }
                finally
                {
                    context.Printer.Unindent();

                    context.Printer.PrintLn();
                    context.Printer.Print(OutputType.Operator, "};");
                }
            }
            else
            {
                // no union is needed
                context.Printer.PrintLn();
                nf.PrintTo(context.Printer, context.LogPrinter, context.Flags);
            }

            currentOffset = union_end;
            index         = last_united_index;
        }
Exemplo n.º 8
0
        /// <summary>
        /// Sets up the <see cref="size"/> and <see cref="pack"/> fields.
        /// </summary>
        private void SetupSizeAndAlignment(Type type)
        {
            // setup alignment
            if (type.StructLayoutAttribute != null)
            {
                this.pack = type.StructLayoutAttribute.Pack;

                switch (this.pack)
                {
                case 0:
                case 1:
                case 2:
                case 4:
                case 8:
                case 16:
                case 32:
                case 64:
                case 128: break;

                default:
                {
                    Log.Add(Errors.ERROR_UnsupportedAlignment, this.pack);
                    this.pack = 0;
                    break;
                }
                }
            }
            if (this.pack == 0)
            {
                this.pack = DefaultPack;
            }
            else
            {
                if (this.pack != DefaultPack &&
                    type.StructLayoutAttribute.Value != LayoutKind.Sequential)
                {
                    Log.Add(Errors.WARN_NoPackEffectOnExplicitLayout);
                }
            }

            int minimum_size;

            // determine the size of the structure based on sizes/offsets of the fields and the given alignment
            if (fields.Length > 0)
            {
                this.size = 0;

                for (int i = 0; i < fields.Length; i++)
                {
                    NativeField nf = fields[i];

                    if (isExplicitLayout)
                    {
                        AlignField(nf, ref this.size, false);

                        int end = (nf.Offset ?? this.size) + nf.Type.TypeSize;
                        if (end > this.size)
                        {
                            this.size = end;
                        }
                    }
                    else
                    {
                        AlignField(nf, ref this.size, true);
                        nf.SetOffset(this.size);

                        this.size += nf.Type.TypeSize;
                    }
                }

                minimum_size = this.size;
                AlignSelf(ref this.size);

                // may only happen when structures are recursively nested
                if (this.size == 0)
                {
                    this.size = 1;
                }
            }
            else
            {
                this.size    = 1;
                minimum_size = this.size;
            }

            // add extra padding if size is specified explicitly
            if (type.StructLayoutAttribute != null)
            {
                int explicit_size = type.StructLayoutAttribute.Size;
                if (explicit_size < 0)
                {
                    Log.Add(Errors.ERROR_InvalidUnmanagedSize, explicit_size);
                }
                else if (explicit_size > 0)
                {
                    if (explicit_size < minimum_size)
                    {
                        Log.Add(Errors.WARN_InsufficientUnmanagedSize, explicit_size, minimum_size);
                        explicit_size = minimum_size;
                    }

                    this.size = explicit_size;

                    AlignSelf(ref explicit_size);
                    if (explicit_size != this.size)
                    {
                        this.unalignedSizeOrOffsets = true;
                    }
                }
            }
        }
Exemplo n.º 9
0
        protected override void Initialize(TypeDefKey key)
        {
            Type type = key.Type;

            Debug.Assert(type.IsValueType || Utility.HasLayout(type));

            this.name        = Utility.GetNameOfType(type);
            this.isBlittable = Utility.IsStructBlittable(type,
                                                         (key.Flags & MarshalFlags.AnsiPlatform) == MarshalFlags.AnsiPlatform);

            // reflect the structure
            FieldInfo[] fis = type.GetFields(bindingFlags);

            this.fields = new NativeField[fis.Length];
            KeyValuePair <int, NativeField>[] fields_with_tokens = new KeyValuePair <int, NativeField> [fis.Length];

            MarshalFlags flags = key.Flags & ~(MarshalFlags.AnsiStrings | MarshalFlags.UnicodeStrings);

            flags |= Utility.GetCharSetMarshalFlag(type);

            for (int i = 0; i < fis.Length; i++)
            {
                NativeField nf = NativeField.FromClrField(fis[i], flags);
                this.fields[i] = nf;

                // check for misaligned reference type fields
                // (can only be misaligned if layout was specified explicitly)
                if (nf.Offset.HasValue && nf.ContainsManagedReference)
                {
                    int ptr_size = TypeName.GetPointerSize((key.Flags & MarshalFlags.Platform64Bit) == MarshalFlags.Platform64Bit);
                    if (nf.Offset.Value % ptr_size != 0)
                    {
                        Log.Add(Errors.ERROR_MisalignedReferenceTypeField, nf.Name);
                    }
                }

                if (nf.Type.TypeSize == 0)
                {
                    // this means that the field type is another structure whose size has not been set up
                    // yet -> there are circular dependencies among structures
                    this.isInvalid = true;

                    Log.Add(Errors.ERROR_RecursiveStructureDeclaration, nf.Name);
                }

                if (type.IsExplicitLayout && !nf.Offset.HasValue)
                {
                    Log.Add(Errors.ERROR_NoFieldOffsetInSequentialLayout, nf.Name);
                }

                fields_with_tokens[i] = new KeyValuePair <int, NativeField>(fis[i].MetadataToken, nf);
            }

            // sort fields to reflect the layout
            if (type.IsExplicitLayout)
            {
                this.isExplicitLayout = true;

                // explicit layout - sort according to offsets
                Array.Sort <KeyValuePair <int, NativeField>, NativeField>(
                    fields_with_tokens,
                    this.fields,
                    ExplicitFieldComparer.Instance);

                // managed references overlapping with other fields are not checked here - such errors are
                // reported by the loader and assemblies containing these types are never loaded
            }
            else
            {
                // sequential layout - sort according to metadata tokens
                Array.Sort <KeyValuePair <int, NativeField>, NativeField>(
                    fields_with_tokens,
                    this.fields,
                    SequentialFieldComparer.Instance);
            }

            SetupSizeAndAlignment(type);
            SetupIsUnionFlag();
        }
Exemplo n.º 10
0
        private int ComputeLastUnitedField(int firstIndex, out int unionEnd)
        {
            Debug.Assert(isExplicitLayout && firstIndex >= 0 && firstIndex < fields.Length);

            NativeField nf = fields[firstIndex];

            // are there more fields?
            if (firstIndex == fields.Length - 1 || !nf.Offset.HasValue)
            {
                unionEnd = (nf.Offset ?? 0) + nf.Type.TypeSize;
                return(firstIndex);
            }

            int union_start = nf.Offset.Value;

            unionEnd = union_start + nf.Type.TypeSize;

            int last_index = firstIndex;
            int previous_last_index, previous_union_end;

            do
            {
                previous_last_index = last_index;
                previous_union_end  = unionEnd;

                for (int i = firstIndex + 1; i < fields.Length; i++)
                {
                    nf = fields[i];

                    // we need offsets of all fields
                    if (!nf.Offset.HasValue)
                    {
                        return(last_index);
                    }

                    if (nf.Offset.Value >= unionEnd)
                    {
                        if (!unalignedSizeOrOffsets)
                        {
                            // this fields looks like it should be placed after the union
                            // however, if it turns out that under standard alignment rules
                            // the actual offset would be higher, we will switch to pack=1
                            int temp_union_end = unionEnd;
                            AlignField(nf, ref temp_union_end, true);

                            if (nf.Offset.Value < temp_union_end)
                            {
                                // the standard alignment results in too much padding so we
                                // fall back to pack=1 and space it manually
                                unalignedSizeOrOffsets = true;
                            }
                            else if (nf.Offset.Value == temp_union_end && i == last_index + 1)
                            {
                                // let's inflate the union without including the next field
                                // the padding will come implicitly as we are under certain pack
                                // and will eliminate superfluous "noop" artificial padding
                                //
                                // (the purpose of this is to detect cases when the layout is
                                // explicit but in fact results in the same offsets that the
                                // sequential layout would generate)
                                unionEnd = temp_union_end;
                            }
                        }
                    }
                    else
                    {
                        // this field clearly belongs to the union
                        last_index = i;
                        unionEnd   = Math.Max(unionEnd, nf.Offset.Value + nf.Type.TypeSize);
                    }
                }
            }while (last_index != previous_last_index || unionEnd != previous_union_end);

            // we found a fixed point: last_index denotes the last field that should be
            // included in the union and unionEnd is the offset just after the union
            return(last_index);
        }
Exemplo n.º 11
0
        static void Test2(string[] args)
        {
            if (args.Length != 1)
            {
                Console.WriteLine("IrbisInteropTester <irbis_server.ini>");
                return;
            }

            try
            {
                ServerConfiguration configuration
                    = ServerConfiguration.FromIniFile(args[0]);
                using (Irbis64Dll irbis = new Irbis64Dll(configuration))
                {
                    Console.WriteLine
                    (
                        "Irbis64.dll version={0}",
                        Irbis64Dll.GetDllVersion()
                    );

                    irbis.UseDatabase("ibis");
                    //irbis.UseDatabase("ISTU");
                    Console.WriteLine
                    (
                        "Max MFN={0}",
                        irbis.GetMaxMfn()
                    );

                    string briefPft = irbis.GetPftPath("brief");
                    irbis.SetFormat("@" + briefPft);

                    for (int mfn = 10; mfn < 20; mfn++)
                    {
                        irbis.ReadRecord(mfn);
                        Console.WriteLine("Read record MFN={0}", mfn);

                        NativeRecord record = irbis.GetRecord();
                        Console.WriteLine(record);

                        string text = irbis.FormatRecord();
                        Console.WriteLine(text);

                        Console.WriteLine();
                    }

                    Console.WriteLine();

                    Console.WriteLine
                    (
                        "Record offset={0}, formatted offset={1}",
                        irbis.Layout.Value.RecordOffset,
                        irbis.Layout.Value.FormattedOffset
                    );

                    Console.WriteLine();

                    TermInfo[] terms = irbis.ListTerms("K=", 50);
                    for (int i = 0; i < terms.Length; i++)
                    {
                        Console.WriteLine(terms[i]);
                    }

                    Console.WriteLine();

                    terms = irbis.ExactSearchTrimEx("K=БЕТОН", 200);
                    for (int i = 0; i < terms.Length; i++)
                    {
                        Console.WriteLine(terms[i]);
                    }

                    Console.WriteLine();

                    TermLink[] links = irbis.ExactSearchLinks
                                       (
                        "K=1 КЛАСС"
                                       );
                    for (int i = 0; i < links.Length; i++)
                    {
                        Console.WriteLine(links[i]);
                    }

                    Console.WriteLine();

                    links = irbis.ExactSearchTrimLinks
                            (
                        "K=БЕТОН",
                        200
                            );
                    for (int i = 0; i < links.Length; i++)
                    {
                        Console.WriteLine(links[i]);
                    }

                    Console.WriteLine();

                    IrbisProvider provider = new NativeIrbisProvider(irbis);
                    SearchManager manager  = new SearchManager(provider);
                    SearchContext context  = new SearchContext(manager, provider);
                    links = irbis.Search("K=БЕТОН", context);
                    for (int i = 0; i < links.Length; i++)
                    {
                        Console.WriteLine(links[i]);
                    }

                    Console.WriteLine();

                    links = irbis.Search("K=БЕТОН * K=ЖЕЛЕЗО$", context);
                    for (int i = 0; i < links.Length; i++)
                    {
                        Console.WriteLine(links[i]);
                    }

                    Console.WriteLine();

                    string testDatabase = Path.Combine
                                          (
                        Path.GetDirectoryName
                        (
                            Assembly.GetEntryAssembly().Location
                        )
                        .ThrowIfNull("directory is unknown"),
                        "TestDb"
                                          );

                    irbis.UseStandaloneDatabase
                    (
                        testDatabase,
                        "TestDb"
                    );

                    for (int i = 0; i < 10; i++)
                    {
                        int          number = i + 1;
                        NativeRecord record = new NativeRecord();
                        for (int j = 0; j < 10; j++)
                        {
                            NativeField field = new NativeField
                            {
                                Tag   = 100 + j,
                                Value = "Запись номер " + number
                                        + " поле " + (100 + j)
                            };
                            record.Fields.Add(field);
                        }

                        irbis.NewRecord();
                        irbis.SetRecord(record);
                        irbis.WriteRecord(true, false);

                        irbis.SetFormat("v100");
                        string text = irbis.FormatRecord();
                        Console.WriteLine(text);
                    }
                }
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception);
            }
        }
Exemplo n.º 12
0
        private static void LayoutUnmanagedPrintoutTest()
        {
            string file_name = "_test.cpp";

            Console.WriteLine("running ValueTypeUnmanagedPrintoutTest...");

            // we'll generate a C++ source file with all the unmanaged structures
            // - it should compile
            // - the C++ sizeof operator should return the intended size
            // - the C++ offsetof macro should return the same offsets as Marshal.OffsetOf

            Console.WriteLine("  generating definitions...");

            using (TextWriterCodePrinter printer = new TextWriterCodePrinter(new StreamWriter(file_name)))
            {
                // prepare a memory printer to print main to
                CodeMemoryPrinter main_printer = new CodeMemoryPrinter();

                main_printer.PrintLn(OutputType.Other, "#define VERIFY(cond) if (!(cond)) printf(\"* \\\"%s\\\" violated\\n\", #cond)");

                main_printer.PrintLn(OutputType.Other, "int main()");
                main_printer.Print(OutputType.Other, "{");
                main_printer.Indent();
                main_printer.PrintLn();

                LogMemoryPrinter log_printer = new LogMemoryPrinter();

                printer.PrintLn(OutputType.Other, "#include <stddef.h>");
                printer.PrintLn(OutputType.Other, "#include <stdio.h>");
                printer.PrintLn(OutputType.Other, "#include <windows.h>");
                printer.PrintLn(OutputType.Other, "#include <oaidl.h>");

                printer.PrintLn();

                int counter = 0;
                foreach (string assemblyString in testAssemblies)
                {
                    Assembly assembly = Assembly.Load(assemblyString);

                    foreach (Type type in assembly.GetTypes())
                    {
                        if (!type.IsAutoClass)
                        {
                            int size_reported_by_clr;

                            try
                            {
                                // will fail when CLR thinks the type has no layout
                                size_reported_by_clr = Marshal.SizeOf(type);
                            }
                            catch (Exception)
                            {
                                continue;
                            }

                            MarshalFlags flags = MarshalFlags.AnsiStrings | MarshalFlags.StructField;
                            if (runningOn64Bit)
                            {
                                flags |= MarshalFlags.Platform64Bit;
                            }

                            NativeType        native_type     = NativeType.FromClrType(type, flags);
                            DefinedNativeType def_native_type = native_type as DefinedNativeType;

                            if (def_native_type != null)
                            {
                                // dump the "closure" of this definition to a namespace
                                string ns_name = String.Format("_CLR_{0}", counter++);

                                printer.PrintLn(OutputType.Other, "namespace " + ns_name);
                                printer.Print(OutputType.Other, "{");
                                printer.Indent();
                                printer.PrintLn();

                                NativeTypeDefinitionSet set = new NativeTypeDefinitionSet();
                                set.Add(def_native_type.Definition);
                                def_native_type.Definition.GetDefinitionsRecursive(set, def_native_type.Definition);

                                // enumerate the closure (will respect dependencies and return definitions
                                // in a correct order introducing forward declarations if necessary)
                                foreach (NativeTypeDefinition def in set)
                                {
                                    def.PrintTo(printer, log_printer,
                                                //PrintFlags.UsePlainC |
                                                PrintFlags.UseDefinedComInterfaces |
                                                PrintFlags.MangleEnumFields);

                                    printer.PrintLn();
                                    printer.PrintLn();
                                }

                                printer.Unindent();
                                printer.PrintLn();
                                printer.PrintLn(OutputType.Other, "};");

                                // add tests to main()
                                main_printer.PrintLn(OutputType.Other, String.Format(
                                                         "VERIFY(sizeof({0}::{1}) == {2});",
                                                         ns_name,
                                                         def_native_type.Definition.Name,
                                                         size_reported_by_clr));

                                StructureDefinition struct_def = def_native_type.Definition as StructureDefinition;
                                if (struct_def != null)
                                {
                                    for (int i = 0; i < struct_def.FieldCount; i++)
                                    {
                                        NativeField nf = struct_def.GetField(i);

                                        int offset;
                                        try
                                        {
                                            offset = (int)Marshal.OffsetOf(type, nf.Name);
                                        }
                                        catch (Exception)
                                        {
                                            continue;
                                        }

                                        // if we think we know the offset of this field, we will verify it
                                        main_printer.PrintLn(OutputType.Other, String.Format(
                                                                 "VERIFY(offsetof({0}::{1}, {2}) == {3});",
                                                                 ns_name,
                                                                 def_native_type.Definition.Name,
                                                                 nf.Name,
                                                                 offset));
                                    }
                                }
                            }
                        }
                    }
                }

                main_printer.Print(OutputType.Other, "return 0;");
                main_printer.Unindent();
                main_printer.PrintLn();
                main_printer.PrintLn(OutputType.Other, "}");

                main_printer.ReplayTo(printer);
            }

            Console.WriteLine("  compiling the generated file...");

            ProcessStartInfo start_info = new ProcessStartInfo(
                @"c:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\cl.exe", "/DUNICODE " + file_name);

            start_info.WorkingDirectory       = Directory.GetCurrentDirectory();
            start_info.UseShellExecute        = false;
            start_info.CreateNoWindow         = true;
            start_info.RedirectStandardOutput = true;

            Process cl_proc = Process.Start(start_info);

            cl_proc.WaitForExit();

            Console.WriteLine(cl_proc.StandardOutput.ReadToEnd());

            Console.WriteLine("  running the generated executable...");

            start_info.FileName  = Path.ChangeExtension(file_name, ".exe");
            start_info.Arguments = String.Empty;

            Process tst_proc = Process.Start(start_info);

            tst_proc.WaitForExit();

            Console.WriteLine(tst_proc.StandardOutput.ReadToEnd());
        }