From d0056cdd9338971b6818639830f6499e9163a312 Mon Sep 17 00:00:00 2001 From: Mark Lechtermann Date: Mon, 8 May 2023 07:53:02 +0200 Subject: [PATCH 01/11] build: dotnet version 6.0.408 --- .github/workflows/code-style.yaml | 2 -- README.md | 36 +++++++++++++++---------------- global.json | 2 +- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/.github/workflows/code-style.yaml b/.github/workflows/code-style.yaml index b266cae..854ad52 100644 --- a/.github/workflows/code-style.yaml +++ b/.github/workflows/code-style.yaml @@ -23,8 +23,6 @@ jobs: - name: Check dotnet version run: dotnet --version - continue-on-error: false - name: Check code format (editorconfig) run: dotnet format --verify-no-changes - continue-on-error: false diff --git a/README.md b/README.md index 4a26ac0..a75c40b 100644 --- a/README.md +++ b/README.md @@ -4,20 +4,20 @@ [![Nuget:Lib](https://img.shields.io/nuget/v/dSPACE.Runtime.InteropServices?label=dSPACE.Runtime.InteropServices&style=flat)](https://www.nuget.org/packages/dSPACE.Runtime.InteropServices/) [![Nuget:LibBuildTask](https://img.shields.io/nuget/v/dSPACE.Runtime.InteropServices?label=dSPACE.Runtime.InteropServices.BuildTasks&style=flat)](https://www.nuget.org/packages/dSPACE.Runtime.InteropServices.BuildTasks/) -[![Release](https://img.shields.io/github/v/release/dspace-group/dscom?label=release)](https://github.com/dspace-group/dscom/releases) -![License](https://img.shields.io/github/license/dspace-group/dscom) -[![dSPACE](https://img.shields.io/badge/-OpenSource%20powered%20by%20dSPACE-blue)](https://www.dspace.com/) - [![Unit Tests](https://github.com/dspace-group/dscom/actions/workflows/unit-test.yaml/badge.svg)](https://github.com/dspace-group/dscom/actions/workflows/unit-test.yaml) [![Example Tests](https://github.com/dspace-group/dscom/actions/workflows/example-test.yaml/badge.svg)](https://github.com/dspace-group/dscom/actions/workflows/example-test.yaml) [![Code Style Check](https://github.com/dspace-group/dscom/actions/workflows/code-style.yaml/badge.svg)](https://github.com/dspace-group/dscom/actions/workflows/code-style.yaml) The command line client `dscom` is a replacement for `tlbexp.exe` and creates and registers TLBs from .NET assemblies. -The `dSPACE.Runtime.InteropServices` library contains various classes and methods for COM. -It can be used in `net5+` or in `net48` projects. With the library you can register assemblies and classes for COM and programmatically generate TLBs at runtime. +With the library `dSPACE.Runtime.InteropServices` you can, among other things, register assemblies and classes for COM and programmatically generate TLBs at runtime. The `dSPACE.Runtime.InteropServices.BuildTasks` library provides build tasks which can be used to automatically generate TLBs at compile time. -> This is an unstable prerelease. Anything may change at any time! +Example: + +```pwsh +PS C:\> dotnet tool install --global dscom +PS C:\> dscom tlbexport myassembly.dll +``` - [dSPACE COM tools](#dspace-com-tools) - [Introducing](#introducing) @@ -271,17 +271,17 @@ This way the build stops, if the type library is not exported. The build task can be parameterized with the following [properties](https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-properties?view=vs-2022): -| **Name** | **Description** | -| ---------------------------------------------- | ---------------------------------------------------------------------------------------------- | -| _DsComTlbExt | Extension of the resulting type library.
Default Value: `.tlb` | -| _DsComForceToolUsage | Use DsCom Exe files to create the TLB
Default value: `false` | false | -| DsComTypeLibraryUniqueId | Overwrite the library UUID
Default Value: Empty Guid | -| DsComOverideLibraryName | Overwrite the IDL name of the library.
Default Value: Empty string | -| DsComRegisterTypeLibrariesAfterBuild | Use regasm call after the build to register type library after the build
Default value: `false` | -| DsComTlbExportAutoAddReferences | Add referenced assemblies automatically to type libraries
Default value: `true` | -| DsComTlbExportIncludeReferencesWithoutHintPath | If a `Reference` assembly does not provide a `HintPath` Metadata, the item spec shall be task.
Default value: `false` | -| _DsComExportTypeLibraryTargetFile | Path to the resulting file.
Default value: `$(TargetDir)\$(TargetName)$(_DsComTlbExt)` * | -| _DsComExportTypeLibraryAssemblyFile | Path to the source assembly file.
Default value: `$(TargetPath)` * | +| **Name** | **Description** | +| ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| _DsComTlbExt | Extension of the resulting type library.
Default Value: `.tlb` | +| _DsComForceToolUsage | Use DsCom Exe files to create the TLB
Default value: `false` | false | +| DsComTypeLibraryUniqueId | Overwrite the library UUID
Default Value: Empty Guid | +| DsComOverideLibraryName | Overwrite the IDL name of the library.
Default Value: Empty string | +| DsComRegisterTypeLibrariesAfterBuild | Use regasm call after the build to register type library after the build
Default value: `false` | +| DsComTlbExportAutoAddReferences | Add referenced assemblies automatically to type libraries
Default value: `true` | +| DsComTlbExportIncludeReferencesWithoutHintPath | If a `Reference` assembly does not provide a `HintPath` Metadata, the item spec shall be task.
Default value: `false` | +| _DsComExportTypeLibraryTargetFile | Path to the resulting file.
Default value: `$(TargetDir)\$(TargetName)$(_DsComTlbExt)` * | +| _DsComExportTypeLibraryAssemblyFile | Path to the source assembly file.
Default value: `$(TargetPath)` * | *) This value cannot be overridden. diff --git a/global.json b/global.json index 5eba956..534c5d8 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "6.0.406", + "version": "6.0.408", "rollForward": "latestPatch" } } \ No newline at end of file From 88cd3d3409f4e090f63466d165fa488471c10cd9 Mon Sep 17 00:00:00 2001 From: Mark Lechtermann Date: Mon, 8 May 2023 08:02:29 +0200 Subject: [PATCH 02/11] build: debug --- .github/workflows/code-style.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/code-style.yaml b/.github/workflows/code-style.yaml index 854ad52..f6a26d4 100644 --- a/.github/workflows/code-style.yaml +++ b/.github/workflows/code-style.yaml @@ -24,5 +24,17 @@ jobs: - name: Check dotnet version run: dotnet --version + - name: Check dotnet version + run: dotnet format --version + + - name: Check dotnet version + run: echo $env:Path + + - name: Check dotnet version + run: dir "C:\Program Files\dotnet" + + - name: Check dotnet version + run: gcm dotnet + - name: Check code format (editorconfig) run: dotnet format --verify-no-changes From 54e8128b7829167aac646ce9612dc2b8a98cbae3 Mon Sep 17 00:00:00 2001 From: Mark Lechtermann Date: Mon, 8 May 2023 08:09:16 +0200 Subject: [PATCH 03/11] build: version --- .github/workflows/code-style.yaml | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/.github/workflows/code-style.yaml b/.github/workflows/code-style.yaml index f6a26d4..0aa6075 100644 --- a/.github/workflows/code-style.yaml +++ b/.github/workflows/code-style.yaml @@ -16,25 +16,12 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - global-json-file: global.json + global-json-file: "./global.json" - name: Restore dependencies run: dotnet restore - - name: Check dotnet version - run: dotnet --version - - - name: Check dotnet version - run: dotnet format --version - - - name: Check dotnet version - run: echo $env:Path - - - name: Check dotnet version - run: dir "C:\Program Files\dotnet" - - - name: Check dotnet version - run: gcm dotnet - - name: Check code format (editorconfig) run: dotnet format --verify-no-changes + with: + global-json-file: "./global.json" From 2a513dc289979731f1c9589e9a33e1a1c97e5759 Mon Sep 17 00:00:00 2001 From: Mark Lechtermann Date: Mon, 8 May 2023 08:10:59 +0200 Subject: [PATCH 04/11] build: fix --- .github/workflows/code-style.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/code-style.yaml b/.github/workflows/code-style.yaml index 0aa6075..79ca1ac 100644 --- a/.github/workflows/code-style.yaml +++ b/.github/workflows/code-style.yaml @@ -23,5 +23,3 @@ jobs: - name: Check code format (editorconfig) run: dotnet format --verify-no-changes - with: - global-json-file: "./global.json" From 302a6684f60e0f78e95781d9a338735449636acd Mon Sep 17 00:00:00 2001 From: Mark Lechtermann Date: Mon, 8 May 2023 08:12:58 +0200 Subject: [PATCH 05/11] build: debug --- .github/workflows/code-style.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/code-style.yaml b/.github/workflows/code-style.yaml index 79ca1ac..362395a 100644 --- a/.github/workflows/code-style.yaml +++ b/.github/workflows/code-style.yaml @@ -18,8 +18,14 @@ jobs: with: global-json-file: "./global.json" - - name: Restore dependencies + - name: Clean + run: dotnet clean + + - name: Restore run: dotnet restore + - name: Build + run: dotnet build + - name: Check code format (editorconfig) run: dotnet format --verify-no-changes From 0d824e99194d33610b20bb75b2f9b436bf4d59dd Mon Sep 17 00:00:00 2001 From: Mark Lechtermann Date: Mon, 8 May 2023 08:26:02 +0200 Subject: [PATCH 06/11] build: debug --- .github/workflows/code-style.yaml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/workflows/code-style.yaml b/.github/workflows/code-style.yaml index 362395a..49dafec 100644 --- a/.github/workflows/code-style.yaml +++ b/.github/workflows/code-style.yaml @@ -18,14 +18,25 @@ jobs: with: global-json-file: "./global.json" - - name: Clean - run: dotnet clean - - - name: Restore + - name: Restore dependencies run: dotnet restore - - name: Build - run: dotnet build + - name: Check dotnet version + run: dotnet --version + + - name: Check dotnet version + run: dotnet format --version + + - name: Check dotnet version + run: echo $env:Path + + - name: Check dotnet version + run: dir "C:\Program Files\dotnet" + + - name: Check dotnet version + run: gcm dotnet - name: Check code format (editorconfig) run: dotnet format --verify-no-changes + with: + global-json-file: "./global.json" From 50e12c8b77df5494f73c78370d545a8ad5145dc8 Mon Sep 17 00:00:00 2001 From: Mark Lechtermann Date: Mon, 8 May 2023 08:27:45 +0200 Subject: [PATCH 07/11] build: debug --- .github/workflows/code-style.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/code-style.yaml b/.github/workflows/code-style.yaml index 49dafec..00dd2b6 100644 --- a/.github/workflows/code-style.yaml +++ b/.github/workflows/code-style.yaml @@ -38,5 +38,3 @@ jobs: - name: Check code format (editorconfig) run: dotnet format --verify-no-changes - with: - global-json-file: "./global.json" From a6461c52c80b6430697e3ef5a1b0e5614c6129f4 Mon Sep 17 00:00:00 2001 From: Mark Lechtermann Date: Mon, 8 May 2023 08:30:37 +0200 Subject: [PATCH 08/11] build: debug --- .github/workflows/code-style.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/code-style.yaml b/.github/workflows/code-style.yaml index 00dd2b6..2d0bc72 100644 --- a/.github/workflows/code-style.yaml +++ b/.github/workflows/code-style.yaml @@ -24,17 +24,17 @@ jobs: - name: Check dotnet version run: dotnet --version - - name: Check dotnet version + - name: Check dotnet --format version run: dotnet format --version - - name: Check dotnet version + - name: env run: echo $env:Path - - name: Check dotnet version - run: dir "C:\Program Files\dotnet" + # - name: dir + # run: dir "C:\Program Files\dotnet" - - name: Check dotnet version - run: gcm dotnet + # - name: gcm dotnet + # run: gcm dotnet - name: Check code format (editorconfig) run: dotnet format --verify-no-changes From 497cc3bdaf247b92451c1dd59eac4ef6cfcdb16a Mon Sep 17 00:00:00 2001 From: Mark Lechtermann Date: Mon, 8 May 2023 08:33:03 +0200 Subject: [PATCH 09/11] build: debug --- .github/workflows/code-style.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/code-style.yaml b/.github/workflows/code-style.yaml index 2d0bc72..4c2b1ab 100644 --- a/.github/workflows/code-style.yaml +++ b/.github/workflows/code-style.yaml @@ -24,11 +24,11 @@ jobs: - name: Check dotnet version run: dotnet --version - - name: Check dotnet --format version - run: dotnet format --version + # - name: Check dotnet --format version + # run: dotnet format --version - - name: env - run: echo $env:Path + # - name: env + # run: echo $env:Path # - name: dir # run: dir "C:\Program Files\dotnet" From a15e55a601e515c833b0a9a0daf2315881f6f944 Mon Sep 17 00:00:00 2001 From: Mark Lechtermann Date: Mon, 8 May 2023 08:36:20 +0200 Subject: [PATCH 10/11] build: cleanup --- .github/workflows/code-style.yaml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.github/workflows/code-style.yaml b/.github/workflows/code-style.yaml index 4c2b1ab..966297d 100644 --- a/.github/workflows/code-style.yaml +++ b/.github/workflows/code-style.yaml @@ -24,17 +24,5 @@ jobs: - name: Check dotnet version run: dotnet --version - # - name: Check dotnet --format version - # run: dotnet format --version - - # - name: env - # run: echo $env:Path - - # - name: dir - # run: dir "C:\Program Files\dotnet" - - # - name: gcm dotnet - # run: gcm dotnet - - name: Check code format (editorconfig) run: dotnet format --verify-no-changes From 1d0995d4cce1f09640387f30d1b340c8f52ec7d8 Mon Sep 17 00:00:00 2001 From: Mark Lechtermann Date: Mon, 8 May 2023 08:52:47 +0200 Subject: [PATCH 11/11] build: debug --- .github/workflows/code-style.yaml | 3 + test/ProcessRunner.cs | 194 ++++++++++++++++++++++++++++++ test/Program.cs | 22 ++++ test/test.csproj | 10 ++ 4 files changed, 229 insertions(+) create mode 100644 test/ProcessRunner.cs create mode 100644 test/Program.cs create mode 100644 test/test.csproj diff --git a/.github/workflows/code-style.yaml b/.github/workflows/code-style.yaml index 966297d..9e64740 100644 --- a/.github/workflows/code-style.yaml +++ b/.github/workflows/code-style.yaml @@ -24,5 +24,8 @@ jobs: - name: Check dotnet version run: dotnet --version + - name: Check code format (editorconfig) + run: dotnet run --project .\test\test.csproj + - name: Check code format (editorconfig) run: dotnet format --verify-no-changes diff --git a/test/ProcessRunner.cs b/test/ProcessRunner.cs new file mode 100644 index 0000000..73ce174 --- /dev/null +++ b/test/ProcessRunner.cs @@ -0,0 +1,194 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.CodeAnalysis.Tools.Utilities +{ + public readonly struct ProcessResult + { + public Process Process { get; } + public int ExitCode { get; } + public ReadOnlyCollection OutputLines { get; } + public ReadOnlyCollection ErrorLines { get; } + + public ProcessResult(Process process, int exitCode, ReadOnlyCollection outputLines, ReadOnlyCollection errorLines) + { + Process = process; + ExitCode = exitCode; + OutputLines = outputLines; + ErrorLines = errorLines; + } + } + + public readonly struct ProcessInfo + { + public Process Process { get; } + public ProcessStartInfo StartInfo { get; } + public Task Result { get; } + + public int Id => Process.Id; + + public ProcessInfo(Process process, ProcessStartInfo startInfo, Task result) + { + Process = process; + StartInfo = startInfo; + Result = result; + } + } + + public static class ProcessRunner + { + public static void OpenFile(string file) + { + if (File.Exists(file)) + { + Process.Start(file); + } + } + + public static ProcessInfo CreateProcess( + string executable, + string arguments, + bool lowPriority = false, + string? workingDirectory = null, + bool captureOutput = false, + bool displayWindow = true, + Dictionary? environmentVariables = null, + Action? onProcessStartHandler = null, + CancellationToken cancellationToken = default) => + CreateProcess( + CreateProcessStartInfo(executable, arguments, workingDirectory, captureOutput, displayWindow, environmentVariables), + lowPriority: lowPriority, + onProcessStartHandler: onProcessStartHandler, + cancellationToken: cancellationToken); + + public static ProcessInfo CreateProcess( + ProcessStartInfo processStartInfo, + bool lowPriority = false, + Action? onProcessStartHandler = null, + CancellationToken cancellationToken = default) + { + var errorLines = new List(); + var outputLines = new List(); + var process = new Process(); + var tcs = new TaskCompletionSource(); + + process.EnableRaisingEvents = true; + process.StartInfo = processStartInfo; + + process.OutputDataReceived += (s, e) => + { + if (e.Data != null) + { + outputLines.Add(e.Data); + } + }; + + process.ErrorDataReceived += (s, e) => + { + if (e.Data != null) + { + errorLines.Add(e.Data); + } + }; + + process.Exited += (s, e) => + { + // We must call WaitForExit to make sure we've received all OutputDataReceived/ErrorDataReceived calls + // or else we'll be returning a list we're still modifying. For paranoia, we'll start a task here rather + // than enter right back into the Process type and start a wait which isn't guaranteed to be safe. + Task.Run(() => + { + process.WaitForExit(); + var result = new ProcessResult( + process, + process.ExitCode, + new ReadOnlyCollection(outputLines), + new ReadOnlyCollection(errorLines)); + tcs.TrySetResult(result); + }); + }; + + _ = cancellationToken.Register(() => + { + if (tcs.TrySetCanceled()) + { + // If the underlying process is still running, we should kill it + if (!process.HasExited) + { + try + { + process.Kill(); + } + catch (InvalidOperationException) + { + // Ignore, since the process is already dead + } + } + } + }); + + process.Start(); + onProcessStartHandler?.Invoke(process); + + if (lowPriority) + { + process.PriorityClass = ProcessPriorityClass.BelowNormal; + } + + if (processStartInfo.RedirectStandardOutput) + { + process.BeginOutputReadLine(); + } + + if (processStartInfo.RedirectStandardError) + { + process.BeginErrorReadLine(); + } + + return new ProcessInfo(process, processStartInfo, tcs.Task); + } + + public static ProcessStartInfo CreateProcessStartInfo( + string executable, + string arguments, + string? workingDirectory = null, + bool captureOutput = false, + bool displayWindow = true, + Dictionary? environmentVariables = null) + { + var processStartInfo = new ProcessStartInfo(executable, arguments); + + if (!string.IsNullOrEmpty(workingDirectory)) + { + processStartInfo.WorkingDirectory = workingDirectory; + } + + if (environmentVariables != null) + { + foreach (var pair in environmentVariables) + { + processStartInfo.EnvironmentVariables[pair.Key] = pair.Value; + } + } + + if (captureOutput) + { + processStartInfo.UseShellExecute = false; + processStartInfo.RedirectStandardOutput = true; + processStartInfo.RedirectStandardError = true; + } + else + { + processStartInfo.CreateNoWindow = !displayWindow; + processStartInfo.UseShellExecute = displayWindow; + } + + return processStartInfo; + } + } +} diff --git a/test/Program.cs b/test/Program.cs new file mode 100644 index 0000000..7f3a9b3 --- /dev/null +++ b/test/Program.cs @@ -0,0 +1,22 @@ +using Microsoft.CodeAnalysis.Tools.Utilities; + +internal class Program +{ + private static int Main(string[] args) + { + TryGetDotNetCliVersion(out string a); + Console.WriteLine(a); + + return 0; + } + + + internal static bool TryGetDotNetCliVersion(out string dotnetVersion) + { + var processInfo = ProcessRunner.CreateProcess("dotnet", "--version", captureOutput: true, displayWindow: false); + var versionResult = processInfo.Result.GetAwaiter().GetResult(); + + dotnetVersion = versionResult.OutputLines[0].Trim(); + return true; + } +} diff --git a/test/test.csproj b/test/test.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/test/test.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + +