diff --git a/.github/workflows/dependabot-approve-and-automerge.yml b/.github/workflows/dependabot-approve-and-automerge.yml index 04daa3d5e1d..8ad436085e9 100644 --- a/.github/workflows/dependabot-approve-and-automerge.yml +++ b/.github/workflows/dependabot-approve-and-automerge.yml @@ -8,7 +8,7 @@ permissions: jobs: dependabot: runs-on: ubuntu-latest - if: ${{ github.actor == 'dependabot[bot]' }} + if: ${{ github.actor == 'dependabot[bot]' && github.repository_owner == 'dotnet' }} steps: - name: Dependabot metadata id: metadata diff --git a/azure/sdk-identity-resources-storage/AzureIdentityStorageExample.csproj b/azure/sdk-identity-resources-storage/AzureIdentityStorageExample.csproj index fad9b14c78c..d75fd3b5541 100644 --- a/azure/sdk-identity-resources-storage/AzureIdentityStorageExample.csproj +++ b/azure/sdk-identity-resources-storage/AzureIdentityStorageExample.csproj @@ -20,10 +20,10 @@ - - - - + + + + diff --git a/core/assembly/MetadataLoadContext/MetadataLoadContextSample.csproj b/core/assembly/MetadataLoadContext/MetadataLoadContextSample.csproj index 8e88a3e2560..9c421dab617 100644 --- a/core/assembly/MetadataLoadContext/MetadataLoadContextSample.csproj +++ b/core/assembly/MetadataLoadContext/MetadataLoadContextSample.csproj @@ -6,7 +6,7 @@ - + diff --git a/core/console-apps/NewTypesMsBuild/test/NewTypesTests/NewTypesTests.csproj b/core/console-apps/NewTypesMsBuild/test/NewTypesTests/NewTypesTests.csproj index de4270a1161..0cb7fd1a1e8 100644 --- a/core/console-apps/NewTypesMsBuild/test/NewTypesTests/NewTypesTests.csproj +++ b/core/console-apps/NewTypesMsBuild/test/NewTypesTests/NewTypesTests.csproj @@ -5,9 +5,9 @@ - - - + + + diff --git a/core/diagnostics/DiagnosticScenarios/DiagnosticScenarios.csproj b/core/diagnostics/DiagnosticScenarios/DiagnosticScenarios.csproj index bb4e2bda1da..2c6b28e1be1 100644 --- a/core/diagnostics/DiagnosticScenarios/DiagnosticScenarios.csproj +++ b/core/diagnostics/DiagnosticScenarios/DiagnosticScenarios.csproj @@ -5,7 +5,7 @@ - + diff --git a/core/encoding/cyrillic-to-latin/cs/CyrillicToLatin.csproj b/core/encoding/cyrillic-to-latin/cs/CyrillicToLatin.csproj index e12b5ecb9ae..a4fb324cffe 100644 --- a/core/encoding/cyrillic-to-latin/cs/CyrillicToLatin.csproj +++ b/core/encoding/cyrillic-to-latin/cs/CyrillicToLatin.csproj @@ -6,7 +6,7 @@ - + diff --git a/core/getting-started/golden/test-library/test-library.csproj b/core/getting-started/golden/test-library/test-library.csproj index 199c8497bed..4c3ed0cc444 100644 --- a/core/getting-started/golden/test-library/test-library.csproj +++ b/core/getting-started/golden/test-library/test-library.csproj @@ -6,9 +6,9 @@ - - - + + + diff --git a/core/getting-started/golden/test/test-library/test-library.csproj b/core/getting-started/golden/test/test-library/test-library.csproj index 6a63886a071..05519635c03 100644 --- a/core/getting-started/golden/test/test-library/test-library.csproj +++ b/core/getting-started/golden/test/test-library/test-library.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/core/getting-started/unit-testing-using-dotnet-test/PrimeService.Tests/PrimeService.Tests.csproj b/core/getting-started/unit-testing-using-dotnet-test/PrimeService.Tests/PrimeService.Tests.csproj index 2324dcff0f2..48e2d771358 100644 --- a/core/getting-started/unit-testing-using-dotnet-test/PrimeService.Tests/PrimeService.Tests.csproj +++ b/core/getting-started/unit-testing-using-dotnet-test/PrimeService.Tests/PrimeService.Tests.csproj @@ -6,9 +6,9 @@ - - - + + + diff --git a/core/getting-started/unit-testing-using-mstest/PrimeService.Tests/PrimeService.Tests.csproj b/core/getting-started/unit-testing-using-mstest/PrimeService.Tests/PrimeService.Tests.csproj index b2860c2b953..3a8bdb94972 100644 --- a/core/getting-started/unit-testing-using-mstest/PrimeService.Tests/PrimeService.Tests.csproj +++ b/core/getting-started/unit-testing-using-mstest/PrimeService.Tests/PrimeService.Tests.csproj @@ -5,7 +5,7 @@ - + diff --git a/core/getting-started/unit-testing-using-nunit/PrimeService.Tests/PrimeService.Tests.csproj b/core/getting-started/unit-testing-using-nunit/PrimeService.Tests/PrimeService.Tests.csproj index 98f0cacb989..b6031482f24 100644 --- a/core/getting-started/unit-testing-using-nunit/PrimeService.Tests/PrimeService.Tests.csproj +++ b/core/getting-started/unit-testing-using-nunit/PrimeService.Tests/PrimeService.Tests.csproj @@ -8,9 +8,9 @@ - + - + diff --git a/core/getting-started/unit-testing-vb-dotnet-test/PrimeService.Tests/PrimeService.Tests.vbproj b/core/getting-started/unit-testing-vb-dotnet-test/PrimeService.Tests/PrimeService.Tests.vbproj index 8793ca0c676..56725adcb7e 100644 --- a/core/getting-started/unit-testing-vb-dotnet-test/PrimeService.Tests/PrimeService.Tests.vbproj +++ b/core/getting-started/unit-testing-vb-dotnet-test/PrimeService.Tests/PrimeService.Tests.vbproj @@ -7,9 +7,9 @@ - - - + + + diff --git a/core/getting-started/unit-testing-vb-mstest/PrimeService.Tests/PrimeService.Tests.vbproj b/core/getting-started/unit-testing-vb-mstest/PrimeService.Tests/PrimeService.Tests.vbproj index b11fc7618df..d3129446921 100644 --- a/core/getting-started/unit-testing-vb-mstest/PrimeService.Tests/PrimeService.Tests.vbproj +++ b/core/getting-started/unit-testing-vb-mstest/PrimeService.Tests/PrimeService.Tests.vbproj @@ -7,7 +7,7 @@ - + diff --git a/core/getting-started/unit-testing-vb-nunit/PrimeService.Tests/PrimeService.Tests.vbproj b/core/getting-started/unit-testing-vb-nunit/PrimeService.Tests/PrimeService.Tests.vbproj index a02fcbac93d..63b1ce53df9 100644 --- a/core/getting-started/unit-testing-vb-nunit/PrimeService.Tests/PrimeService.Tests.vbproj +++ b/core/getting-started/unit-testing-vb-nunit/PrimeService.Tests/PrimeService.Tests.vbproj @@ -8,9 +8,9 @@ - + - + diff --git a/core/getting-started/unit-testing-with-fsharp-mstest/MathService.Tests/MathService.Tests.fsproj b/core/getting-started/unit-testing-with-fsharp-mstest/MathService.Tests/MathService.Tests.fsproj index 40555f9eb85..c6856cd4b16 100644 --- a/core/getting-started/unit-testing-with-fsharp-mstest/MathService.Tests/MathService.Tests.fsproj +++ b/core/getting-started/unit-testing-with-fsharp-mstest/MathService.Tests/MathService.Tests.fsproj @@ -12,7 +12,7 @@ - + diff --git a/core/getting-started/unit-testing-with-fsharp-nunit/MathService.Tests/MathService.Tests.fsproj b/core/getting-started/unit-testing-with-fsharp-nunit/MathService.Tests/MathService.Tests.fsproj index b6a1bd9a5a1..3a49a114f59 100644 --- a/core/getting-started/unit-testing-with-fsharp-nunit/MathService.Tests/MathService.Tests.fsproj +++ b/core/getting-started/unit-testing-with-fsharp-nunit/MathService.Tests/MathService.Tests.fsproj @@ -13,9 +13,9 @@ - + - + diff --git a/core/getting-started/unit-testing-with-fsharp/MathService.Tests/MathService.Tests.fsproj b/core/getting-started/unit-testing-with-fsharp/MathService.Tests/MathService.Tests.fsproj index c9f8c71fc6f..3f340e1bdb6 100644 --- a/core/getting-started/unit-testing-with-fsharp/MathService.Tests/MathService.Tests.fsproj +++ b/core/getting-started/unit-testing-with-fsharp/MathService.Tests/MathService.Tests.fsproj @@ -12,9 +12,9 @@ - - - + + + diff --git a/core/interop/source-generation/ComWrappersGeneration/.gitignore b/core/interop/source-generation/ComWrappersGeneration/.gitignore new file mode 100644 index 00000000000..3195f839657 --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/.gitignore @@ -0,0 +1 @@ +OutputFiles diff --git a/core/interop/source-generation/ComWrappersGeneration/Client/Client.csproj b/core/interop/source-generation/ComWrappersGeneration/Client/Client.csproj new file mode 100644 index 00000000000..f35c6e9ddde --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/Client/Client.csproj @@ -0,0 +1,13 @@ + + + + Exe + net8.0 + enable + enable + + + + + + diff --git a/core/interop/source-generation/ComWrappersGeneration/Client/Program.cs b/core/interop/source-generation/ComWrappersGeneration/Client/Program.cs new file mode 100644 index 00000000000..11fcf8a6b72 --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/Client/Program.cs @@ -0,0 +1,79 @@ +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +[assembly: DisableRuntimeMarshalling] + +namespace Tutorial; + +public class Program +{ + public static unsafe void Main(string[] args) + { + var clsid = new Guid(Clsids.Calculator); + var iid = new Guid(ICalculator.IID); + Console.WriteLine($"Client: Requesting a Calculator (CLSID {clsid}) with ICalculator (IID {iid})"); + int hr = Ole32.CoCreateInstance(ref clsid, /* No aggregation */ 0, (uint)Ole32.CLSCTX.CLSCTX_INPROC_SERVER, ref iid, out object comObject); + Marshal.ThrowExceptionForHR(hr); + ICalculator calculator = (ICalculator) comObject; + + int a = 5; + int b = 3; + int c; + c = calculator.Add(a, b); + Console.WriteLine($"Client: {a} + {b} = {c}"); + c = calculator.Subtract(a, b); + Console.WriteLine($"Client: {a} - {b} = {c}"); + } +} + +internal static unsafe partial class Ole32 +{ + // https://docs.microsoft.com/windows/win32/api/combaseapi/nf-combaseapi-cocreateinstance + [LibraryImport(nameof(Ole32))] + public static partial int CoCreateInstance( + ref Guid rclsid, + nint pUnkOuter, + uint dwClsContext, + ref Guid riid, + // The default ComInterfaceMarshaller will unwrap a .NET object if it can tell the COM instance is a ComWrapper. + // This causes issues when casting to ICalculator, since the Server's Calculator class doesn't implement the Client's interface. + // UniqueComInterfaceMarshaller doesn't try to unwrap the object and always creates a new COM object. + [MarshalUsing(typeof(UniqueComInterfaceMarshaller))] + out object ppv); + + // https://learn.microsoft.com/windows/win32/api/wtypesbase/ne-wtypesbase-clsctx + public enum CLSCTX : uint + { + CLSCTX_INPROC_SERVER = 0x1, + CLSCTX_INPROC_HANDLER = 0x2, + CLSCTX_LOCAL_SERVER = 0x4, + CLSCTX_INPROC_SERVER16 = 0x8, + CLSCTX_REMOTE_SERVER = 0x10, + CLSCTX_INPROC_HANDLER16 = 0x20, + CLSCTX_RESERVED1 = 0x40, + CLSCTX_RESERVED2 = 0x80, + CLSCTX_RESERVED3 = 0x100, + CLSCTX_RESERVED4 = 0x200, + CLSCTX_NO_CODE_DOWNLOAD = 0x400, + CLSCTX_RESERVED5 = 0x800, + CLSCTX_NO_CUSTOM_MARSHAL = 0x1000, + CLSCTX_ENABLE_CODE_DOWNLOAD = 0x2000, + CLSCTX_NO_FAILURE_LOG = 0x4000, + CLSCTX_DISABLE_AAA = 0x8000, + CLSCTX_ENABLE_AAA = 0x10000, + CLSCTX_FROM_DEFAULT_CONTEXT = 0x20000, + CLSCTX_ACTIVATE_X86_SERVER = 0x40000, + CLSCTX_ACTIVATE_32_BIT_SERVER, + CLSCTX_ACTIVATE_64_BIT_SERVER = 0x80000, + CLSCTX_ENABLE_CLOAKING = 0x100000, + CLSCTX_APPCONTAINER = 0x400000, + CLSCTX_ACTIVATE_AAA_AS_IU = 0x800000, + CLSCTX_RESERVED6 = 0x1000000, + CLSCTX_ACTIVATE_ARM32_SERVER = 0x2000000, + CLSCTX_ALLOW_LOWER_TRUST_REGISTRATION, + CLSCTX_PS_DLL = 0x80000000, + } +} diff --git a/core/interop/source-generation/ComWrappersGeneration/ComWrappersGeneration.sln b/core/interop/source-generation/ComWrappersGeneration/ComWrappersGeneration.sln new file mode 100644 index 00000000000..902bb554635 --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/ComWrappersGeneration.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "Client\Client.csproj", "{065F345B-901A-4BCD-8CAF-ACBB6B6910F8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csproj", "{DCA455A0-57CF-467F-9D5D-10C95EAA9441}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {065F345B-901A-4BCD-8CAF-ACBB6B6910F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {065F345B-901A-4BCD-8CAF-ACBB6B6910F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {065F345B-901A-4BCD-8CAF-ACBB6B6910F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {065F345B-901A-4BCD-8CAF-ACBB6B6910F8}.Release|Any CPU.Build.0 = Release|Any CPU + {DCA455A0-57CF-467F-9D5D-10C95EAA9441}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DCA455A0-57CF-467F-9D5D-10C95EAA9441}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DCA455A0-57CF-467F-9D5D-10C95EAA9441}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DCA455A0-57CF-467F-9D5D-10C95EAA9441}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/core/interop/source-generation/ComWrappersGeneration/Directory.Build.props b/core/interop/source-generation/ComWrappersGeneration/Directory.Build.props new file mode 100644 index 00000000000..225cf8b5742 --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/Directory.Build.props @@ -0,0 +1,14 @@ + + + + net8.0 + true + true + bin\Generated + $(MSBuildThisFileDirectory)\OutputFiles\$(MSBuildProjectName)\ + + + + + + diff --git a/core/interop/source-generation/ComWrappersGeneration/README.md b/core/interop/source-generation/ComWrappersGeneration/README.md new file mode 100644 index 00000000000..1be774bb52f --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/README.md @@ -0,0 +1,38 @@ +--- +languages: +- csharp +products: +- dotnet +page_type: sample +name: "Source-Generated COM Sample" +urlFragment: "generated-comwrappers" +description: "A .NET codebase that uses source-generated COM in .NET" +--- +# .NET Source-Generated COM Sample + +This tutorial demonstrates how to use COM source generators in .NET 8+ to create a COM server and client for in-process COM. + +This example defines an interface `ICalculator` that provides `Add` and `Subtract` methods. The server provides an implementation of `ICalculator` for the client to use after the server has been registered. The client project creates an instance of the object using the [`CoCreateInstance`](https://learn.microsoft.com/windows/win32/api/combaseapi/nf-combaseapi-cocreateinstance) Win32 method, and calls methods on the object. + +This sample supports NativeAOT and standard CoreCLR deployments. The native methods that the Windows COM system requires are exported automatically with the `[UnmanagedCallersOnly]` attribute when publishing with NativeAOT. For CoreCLR, the [DNNE](https://github.com/AaronRobinsonMSFT/DNNE) package is used to provide the exported functions. + +## Prerequisites + +- .NET 8+ SDK +- Windows 10+ OS + +## Build and Run + +### NativeAOT + +Build the Native AOT binaries by running `dotnet publish -r ` where `` is the RuntimeIdentifier for your OS, for example `win-x64`. The projects will copy the binaries to the `OutputFiles\` directory. After publishing, use `regsvr32.exe` to register `Server.dll` with COM by running run `regsvr.exe .\OutputFiles\Server\Server.dll`. Then, run the client application `.\OutputFiles\Client\Client.exe` and observe the output as it activates and uses a COM instance from `Server.dll`. + +### CoreCLR + +Build the projects by running `dotnet publish`. The projects will copy the binaries to the `OutputFiles\` directory. After publishing, use `regsvr32.exe` to register the native binary produced by DNNE, `ServerNE.dll` by running `regsvr.exe .\OutputFiles\Server\ServerNE.dll`. `ServerNE.dll` will start the .NET runtime and call the exported methods in the managed `Server.dll` which register the server with COM. Then, run the client application `.\OutputFiles\Client\Client.exe` and observe the output as it activates and uses a COM instance from `ServerNE.dll`. + +## See also + +- [ComWrappers source generation](https://learn.microsoft.com/dotnet/standard/native-interop/comwrappers-source-generation) +- [Native exports in NativeAOT](https://learn.microsoft.com/dotnet/core/deploying/native-aot/interop#native-exports) +- [COM interop in .NET](https://learn.microsoft.com/dotnet/standard/native-interop/cominterop) diff --git a/core/interop/source-generation/ComWrappersGeneration/Server/Calculator.cs b/core/interop/source-generation/ComWrappersGeneration/Server/Calculator.cs new file mode 100644 index 00000000000..9c57e2474cd --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/Server/Calculator.cs @@ -0,0 +1,15 @@ +using System; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using Microsoft.Win32; + +namespace Tutorial; + +[GeneratedComClass] +[Guid(Clsid)] +internal partial class Calculator : ICalculator +{ + public int Add(int a, int b) => a + b; + public int Subtract(int a, int b) => a - b; + internal const string Clsid = Clsids.Calculator; +} diff --git a/core/interop/source-generation/ComWrappersGeneration/Server/ClassFactory.cs b/core/interop/source-generation/ComWrappersGeneration/Server/ClassFactory.cs new file mode 100644 index 00000000000..8637c0b786b --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/Server/ClassFactory.cs @@ -0,0 +1,24 @@ +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +namespace Tutorial; + +[GeneratedComClass] +public unsafe partial class ClassFactory : IClassFactory +{ + public static ClassFactory Instance { get; } = new ClassFactory(); + public void CreateInstance(nint pOuter, in Guid iid, out object? ppInterface) + { + Console.WriteLine($"Server: IID requested from ClassFactory.CreateInstance: {iid}"); + if (pOuter != 0) + { + ppInterface = null; + const int CLASS_E_NOAGGREGATION = unchecked((int)0x80040110); + throw new COMException("Class does not support aggregation", CLASS_E_NOAGGREGATION); + } + Calculator calculator = new(); + ppInterface = calculator; + } + + public void LockServer(bool fLock) { } +} diff --git a/core/interop/source-generation/ComWrappersGeneration/Server/DNNE.cs b/core/interop/source-generation/ComWrappersGeneration/Server/DNNE.cs new file mode 100644 index 00000000000..20b4482294e --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/Server/DNNE.cs @@ -0,0 +1,27 @@ +namespace DNNE; + +/// +/// Provide C code to be defined early in the generated C header file. +/// +/// +/// This attribute is respected on an exported method declaration or on a parameter for the method. +/// The following header files will be included prior to the code being defined. +/// - stddef.h +/// - stdint.h +/// - dnne.h +/// +internal class C99DeclCodeAttribute : System.Attribute +{ + public C99DeclCodeAttribute(string code) { } +} + +/// +/// Define the C type to be used. +/// +/// +/// The level of indirection should be included in the supplied string. +/// +internal class C99TypeAttribute : System.Attribute +{ + public C99TypeAttribute(string code) { } +} diff --git a/core/interop/source-generation/ComWrappersGeneration/Server/Exports.cs b/core/interop/source-generation/ComWrappersGeneration/Server/Exports.cs new file mode 100644 index 00000000000..b66c87c3ab8 --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/Server/Exports.cs @@ -0,0 +1,108 @@ +using System; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using Microsoft.Win32; + +namespace Tutorial; + +public static unsafe class Exports +{ + /// + /// Returns a pointer to an IClassFactory instance that corresponds to the requested . + /// is expected to be the IID of IClassFactory. + /// This method is called by the COM system when a client requests an object that this server has registered. + /// + /// + [UnmanagedCallersOnly(EntryPoint = nameof(DllGetClassObject))] + public static int DllGetClassObject([DNNE.C99Type("void*")] Guid* classId, [DNNE.C99Type("void*")] Guid* interfaceId, nint* ppIClassFactory) + { + Console.WriteLine($"Server: Class ID requested from DllGetClassObject: {*classId}"); + Console.WriteLine($"Server: Interface ID requested from DllGetClassObject: {*interfaceId}"); + if (*classId != new Guid(Clsids.Calculator) + || *interfaceId != new Guid(IClassFactory.IID)) + { + *ppIClassFactory = 0; + const int CLASS_E_CLASSNOTAVAILABLE = unchecked((int)0x80040111); + return CLASS_E_CLASSNOTAVAILABLE; + } + ClassFactory factory = ClassFactory.Instance; + nint pIUnknown = (nint)ComInterfaceMarshaller.ConvertToUnmanaged(factory); + // Call QI on the COM ptr from COM wrappers to get the requested interface pointer + // This is IClassFactory for CoCreateInstance + int hr = Marshal.QueryInterface(pIUnknown, in *interfaceId, out *ppIClassFactory); + Marshal.Release(pIUnknown); + if (hr != 0) + { + Console.WriteLine($"Server: QueryInterface in DllGetClassObject failed: {hr:x}"); + return hr; + } + return 0; + } + + /// + /// Registers the server with the COM system. + /// Called by regsvr32.exe when run with this .dll as the argument. + /// + /// + [UnmanagedCallersOnly(EntryPoint = nameof(DllRegisterServer))] + public static int DllRegisterServer() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return -1; + + if (!FileUtils.TryGetDllPath(out string? dllPath)) + { + const int SELFREG_E_CLASS = unchecked((int)0x80040201); + return SELFREG_E_CLASS; + } + CreateComRegistryEntryForClass(Calculator.Clsid, nameof(Calculator), dllPath!); + return 0; + } + + static void CreateComRegistryEntryForClass(string clsid, string className, string dllPath) + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + throw new InvalidOperationException(); + + string progId = GetProgId(className); + + using (RegistryKey key = Registry.CurrentUser.CreateSubKey($$"""SOFTWARE\Classes\CLSID\{{{clsid}}}""")) + { + key.SetValue(null, className, RegistryValueKind.String); + key.SetValue("ProgId", progId, RegistryValueKind.String); + } + using (RegistryKey key = Registry.CurrentUser.CreateSubKey($$"""SOFTWARE\Classes\CLSID\{{{clsid}}}\InprocServer32""")) + { + key.SetValue(null, dllPath, RegistryValueKind.String); + key.SetValue("ThreadingModel", "Both", RegistryValueKind.String); + } + using (RegistryKey key = Registry.CurrentUser.CreateSubKey($$"""SOFTWARE\Classes\{{{progId}}}""")) + { + key.SetValue(null, className, RegistryValueKind.String); + key.SetValue("CLSID", clsid, RegistryValueKind.String); + } + } + + /// + /// Unregisters the server from the COM system. + /// Called by regsvr32.exe when run with the -u flag and this .dll as the argument + /// + /// + [UnmanagedCallersOnly(EntryPoint = nameof(DllUnregisterServer))] + public static int DllUnregisterServer() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + throw new InvalidOperationException(); + + string clsid = Calculator.Clsid; + string progId = GetProgId(nameof(Calculator)); + + Registry.CurrentUser.DeleteSubKeyTree($$"""SOFTWARE\Classes\CLSID\{{{clsid}}}"""); + Registry.CurrentUser.DeleteSubKeyTree($$"""SOFTWARE\Classes\{{{progId}}}"""); + return 0; + } + + public static string GetProgId(string className) => $"Tutorial.{className}.0"; +} diff --git a/core/interop/source-generation/ComWrappersGeneration/Server/FileUtils.cs b/core/interop/source-generation/ComWrappersGeneration/Server/FileUtils.cs new file mode 100644 index 00000000000..7ef0b9838da --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/Server/FileUtils.cs @@ -0,0 +1,52 @@ +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Tutorial; + +public static class FileUtils +{ + /// + /// Gets the path to the NativeDll that the COM system should use to call the native exports + /// + [UnconditionalSuppressMessage(category: "SingleFile", checkId: "IL3000" /* Avoid accessing Assembly file path when publishing as a single file */, Justification = "The code is aware the `Assembly.Location` may be an empty string and falls back to Win32 APIs")] + public static unsafe bool TryGetDllPath([NotNullWhen(true)] out string? dllPath) + { + // Try using reflection to get the path to the native COM entry points + dllPath = typeof(FileUtils).Assembly.Location; + // Assembly.Location is an empty string in single file and NativeAOT + // Fall back to Windows APIs if Location is empty string + if (dllPath == "" && !TryGetDllPathWin32(out dllPath)) + return false; + // Check if DNNE binary exists and return path to DNNE binary if it exists + const string dnneSuffix = "NE.dll"; + string fileName = Path.GetFileNameWithoutExtension(dllPath); + string directory = Path.GetDirectoryName(dllPath) ?? ""; + string dnnePath = Path.Combine(directory, fileName + dnneSuffix); + if (File.Exists(dnnePath)) + dllPath = dnnePath; + return true; + } + + /// + /// Gets the path to the dll that has the DllRegisterServer address using the Windows APIs + /// + public static unsafe bool TryGetDllPathWin32([NotNullWhen(true)] out string? dllPath) + { + dllPath = null; + bool receivedHandle = Kernel32.GetModuleHandleExW( + Kernel32.GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | Kernel32.GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (nint)(delegate* unmanaged)&Exports.DllRegisterServer, + out nint moduleHandle); + if (!receivedHandle) + return false; + + char[] filePath = new char[256]; + int pathSize = Kernel32.GetModuleFileNameW(moduleHandle, filePath, filePath.Length); + if (pathSize == 0) + return false; + + dllPath = new string(filePath); + return true; + } +} diff --git a/core/interop/source-generation/ComWrappersGeneration/Server/IClassFactory.cs b/core/interop/source-generation/ComWrappersGeneration/Server/IClassFactory.cs new file mode 100644 index 00000000000..9d73feab049 --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/Server/IClassFactory.cs @@ -0,0 +1,18 @@ +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +namespace Tutorial; + +/// +/// The interface that the COM system uses to create new objects when clients use CoCreateInstance. +/// +/// +[GeneratedComInterface] +[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +[Guid(IID)] +internal unsafe partial interface IClassFactory +{ + void CreateInstance(nint outer, in Guid id, [MarshalAs(UnmanagedType.Interface)] out object? iface); + void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock); + public const string IID = "00000001-0000-0000-C000-000000000046"; +} diff --git a/core/interop/source-generation/ComWrappersGeneration/Server/Kernel32.cs b/core/interop/source-generation/ComWrappersGeneration/Server/Kernel32.cs new file mode 100644 index 00000000000..aba76d1d55f --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/Server/Kernel32.cs @@ -0,0 +1,33 @@ +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +internal static partial class Kernel32 +{ + /// + /// Gets a module handle given an address from that module. + /// + /// + [LibraryImport(nameof(Kernel32))] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool GetModuleHandleExW(int flags, nint pAddressInModule, out nint moduleHandle); + + /// + /// Makes the second argument of interpreted as an address in the module rather than a string. + /// + public static int GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 0x00000004; + + /// + /// Makes GetModuleHandleExW not increment the reference count, so we don't need to decrement it ourselves. + /// + public const int GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 0x00000002; + + /// + /// Gets the path to a module given the module handle. + /// + /// + [LibraryImport(nameof(Kernel32), StringMarshalling = StringMarshalling.Utf16)] + public static partial int GetModuleFileNameW( + nint moduleHandle, + [MarshalUsing(CountElementName = nameof(nSize)), Out] char[] FileName, + int nSize); +} diff --git a/core/interop/source-generation/ComWrappersGeneration/Server/Server.csproj b/core/interop/source-generation/ComWrappersGeneration/Server/Server.csproj new file mode 100644 index 00000000000..ed30283e295 --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/Server/Server.csproj @@ -0,0 +1,23 @@ + + + + Library + net8.0 + enable + enable + + + + + + true + + + + + + + + + + diff --git a/core/interop/source-generation/ComWrappersGeneration/Server/server.def b/core/interop/source-generation/ComWrappersGeneration/Server/server.def new file mode 100644 index 00000000000..fad93f81976 --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/Server/server.def @@ -0,0 +1,4 @@ +EXPORTS + DllGetClassObject PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE diff --git a/core/interop/source-generation/ComWrappersGeneration/Shared/ClsIds.cs b/core/interop/source-generation/ComWrappersGeneration/Shared/ClsIds.cs new file mode 100644 index 00000000000..a3423b64b2d --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/Shared/ClsIds.cs @@ -0,0 +1,6 @@ +namespace Tutorial; + +public static class Clsids +{ + public const string Calculator = "99899901-bb69-460c-bf4c-ba122044030e"; +} diff --git a/core/interop/source-generation/ComWrappersGeneration/Shared/ICalculator.cs b/core/interop/source-generation/ComWrappersGeneration/Shared/ICalculator.cs new file mode 100644 index 00000000000..69e8ea6e67e --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/Shared/ICalculator.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +namespace Tutorial; + +[GeneratedComInterface] +[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +[Guid(IID)] +internal partial interface ICalculator +{ + int Add(int a, int b); + int Subtract(int a, int b); + public const string IID = "c67121c6-cf26-431f-adc7-d12fe2448841"; +} diff --git a/core/interop/source-generation/ComWrappersGeneration/global.json b/core/interop/source-generation/ComWrappersGeneration/global.json new file mode 100644 index 00000000000..e5716884662 --- /dev/null +++ b/core/interop/source-generation/ComWrappersGeneration/global.json @@ -0,0 +1,5 @@ +{ + "msbuild-sdks": { + "Microsoft.Build.Traversal": "2.0.2" + } +} \ No newline at end of file diff --git a/core/nativeaot/NativeLibrary/Class1.cs b/core/nativeaot/NativeLibrary/Class1.cs index 281043f3007..288d8a2dad8 100644 --- a/core/nativeaot/NativeLibrary/Class1.cs +++ b/core/nativeaot/NativeLibrary/Class1.cs @@ -8,13 +8,14 @@ namespace NativeLibrary { public class Class1 { - [UnmanagedCallersOnly(EntryPoint = "add")] + // Use common prefix for all entrypoints to avoid symbol name collisions + [UnmanagedCallersOnly(EntryPoint = "aotsample_add")] public static int Add(int a, int b) { return a + b; } - [UnmanagedCallersOnly(EntryPoint = "write_line")] + [UnmanagedCallersOnly(EntryPoint = "aotsample_write_line")] public static int WriteLine(IntPtr pString) { // The marshalling code is typically auto-generated by a custom tool in larger projects. @@ -35,7 +36,7 @@ public static int WriteLine(IntPtr pString) return 0; } - [UnmanagedCallersOnly(EntryPoint = "sumstring")] + [UnmanagedCallersOnly(EntryPoint = "aotsample_sumstring")] public static IntPtr sumstring(IntPtr first, IntPtr second) { // Parse strings from the passed pointers diff --git a/core/nativeaot/NativeLibrary/LoadLibrary.c b/core/nativeaot/NativeLibrary/LoadLibrary.c index 72301eecc3f..bae153b8295 100644 --- a/core/nativeaot/NativeLibrary/LoadLibrary.c +++ b/core/nativeaot/NativeLibrary/LoadLibrary.c @@ -5,11 +5,11 @@ //Set this value accordingly to your workspace settings #if defined(_WIN32) -#define PathToLibrary "bin\\Debug\\net8.0\\win-x64\\publish\\NativeLibrary.dll" +#define PathToLibrary "bin\\Release\\net8.0\\win-x64\\publish\\NativeLibrary.dll" #elif defined(__APPLE__) -#define PathToLibrary "./bin/Debug/net8.0/osx-x64/publish/NativeLibrary.dylib" +#define PathToLibrary "./bin/Release/net8.0/osx-x64/publish/NativeLibrary.dylib" #else -#define PathToLibrary "./bin/Debug/net8.0/linux-x64/publish/NativeLibrary.so" +#define PathToLibrary "./bin/Release/net8.0/linux-x64/publish/NativeLibrary.so" #endif #ifdef _WIN32 @@ -43,11 +43,11 @@ int main() } // Sum two integers - int sum = callSumFunc(PathToLibrary, "add", 2, 8); + int sum = callSumFunc(PathToLibrary, "aotsample_add", 2, 8); printf("The sum is %d \n", sum); // Concatenate two strings - char *sumstring = callSumStringFunc(PathToLibrary, "sumstring", "ok", "ko"); + char *sumstring = callSumStringFunc(PathToLibrary, "aotsample_sumstring", "ok", "ko"); printf("The concatenated string is %s \n", sumstring); // Free string diff --git a/core/nativeaot/NativeLibrary/README.md b/core/nativeaot/NativeLibrary/README.md index efddbdb2f88..fffce86fccb 100644 --- a/core/nativeaot/NativeLibrary/README.md +++ b/core/nativeaot/NativeLibrary/README.md @@ -9,7 +9,7 @@ Create a .NET class library project using `dotnet new classlib -o NativeLibrary` ## Building shared libraries ```bash -> dotnet publish /p:NativeLib=Shared +> dotnet publish /p:NativeLib=Shared --use-current-runtime ``` The above command will drop a shared library (Windows `.dll`, macOS `.dylib`, Linux `.so`) in `./bin/Release/net8.0/[RID]/publish/` folder and will have the same name as the folder in which your source file is present. @@ -67,7 +67,7 @@ For a C# method in the native library to be consumable by external programs, it Apply the attribute to the method, specifying the `EntryPoint`: ```csharp -[UnmanagedCallersOnly(EntryPoint = "add")] +[UnmanagedCallersOnly(EntryPoint = "aotsample_add")] public static int Add(int a, int b) { return a + b; @@ -86,7 +86,7 @@ The sample [source code](Class1.cs) demonstrates common techniques used to stay ## Building static libraries ```bash -> dotnet publish /p:NativeLib=Static +> dotnet publish /p:NativeLib=Static --use-current-runtime ``` The above command will drop a static library (Windows `.lib`, macOS/Linux `.a`) in `./bin/Release/net8.0/[RID]/publish/` folder and will have the same name as the folder in which your source file is present. diff --git a/core/tutorials/using-on-mac-vs-full-solution/WordCounter/TestLibrary/TestLibrary.csproj b/core/tutorials/using-on-mac-vs-full-solution/WordCounter/TestLibrary/TestLibrary.csproj index c99245b32f7..92d596447ec 100644 --- a/core/tutorials/using-on-mac-vs-full-solution/WordCounter/TestLibrary/TestLibrary.csproj +++ b/core/tutorials/using-on-mac-vs-full-solution/WordCounter/TestLibrary/TestLibrary.csproj @@ -5,9 +5,9 @@ - - - + + + diff --git a/csharp/parallel/ParallelExtensionsExtras/ParallelExtensionsExtras.csproj b/csharp/parallel/ParallelExtensionsExtras/ParallelExtensionsExtras.csproj index 37db42ff402..ab2cc80e87e 100644 --- a/csharp/parallel/ParallelExtensionsExtras/ParallelExtensionsExtras.csproj +++ b/csharp/parallel/ParallelExtensionsExtras/ParallelExtensionsExtras.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -9,7 +9,7 @@ - + diff --git a/csharp/roslyn-sdk/SemanticQuickStart/SemanticQuickStart.csproj b/csharp/roslyn-sdk/SemanticQuickStart/SemanticQuickStart.csproj index 30014ce70b5..c13edc4b278 100644 --- a/csharp/roslyn-sdk/SemanticQuickStart/SemanticQuickStart.csproj +++ b/csharp/roslyn-sdk/SemanticQuickStart/SemanticQuickStart.csproj @@ -6,7 +6,7 @@ - + diff --git a/csharp/roslyn-sdk/SyntaxQuickStart/HelloSyntaxTree/HelloSyntaxTree.csproj b/csharp/roslyn-sdk/SyntaxQuickStart/HelloSyntaxTree/HelloSyntaxTree.csproj index 30014ce70b5..c13edc4b278 100644 --- a/csharp/roslyn-sdk/SyntaxQuickStart/HelloSyntaxTree/HelloSyntaxTree.csproj +++ b/csharp/roslyn-sdk/SyntaxQuickStart/HelloSyntaxTree/HelloSyntaxTree.csproj @@ -6,7 +6,7 @@ - + diff --git a/csharp/roslyn-sdk/SyntaxQuickStart/SyntaxWalker/SyntaxWalker.csproj b/csharp/roslyn-sdk/SyntaxQuickStart/SyntaxWalker/SyntaxWalker.csproj index 30014ce70b5..c13edc4b278 100644 --- a/csharp/roslyn-sdk/SyntaxQuickStart/SyntaxWalker/SyntaxWalker.csproj +++ b/csharp/roslyn-sdk/SyntaxQuickStart/SyntaxWalker/SyntaxWalker.csproj @@ -6,7 +6,7 @@ - + diff --git a/csharp/roslyn-sdk/SyntaxTransformationQuickStart/ConstructionCS/ConstructionCS.csproj b/csharp/roslyn-sdk/SyntaxTransformationQuickStart/ConstructionCS/ConstructionCS.csproj index 8a3f3bc88b3..7878a146438 100644 --- a/csharp/roslyn-sdk/SyntaxTransformationQuickStart/ConstructionCS/ConstructionCS.csproj +++ b/csharp/roslyn-sdk/SyntaxTransformationQuickStart/ConstructionCS/ConstructionCS.csproj @@ -6,7 +6,7 @@ - + diff --git a/csharp/roslyn-sdk/SyntaxTransformationQuickStart/TransformationCS/TransformationCS.csproj b/csharp/roslyn-sdk/SyntaxTransformationQuickStart/TransformationCS/TransformationCS.csproj index 30014ce70b5..c13edc4b278 100644 --- a/csharp/roslyn-sdk/SyntaxTransformationQuickStart/TransformationCS/TransformationCS.csproj +++ b/csharp/roslyn-sdk/SyntaxTransformationQuickStart/TransformationCS/TransformationCS.csproj @@ -6,7 +6,7 @@ - + diff --git a/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst.CodeFixes/MakeConst.CodeFixes.csproj b/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst.CodeFixes/MakeConst.CodeFixes.csproj index 8e4bf38f995..38ea3900566 100644 --- a/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst.CodeFixes/MakeConst.CodeFixes.csproj +++ b/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst.CodeFixes/MakeConst.CodeFixes.csproj @@ -7,7 +7,7 @@ - + diff --git a/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst.Test/MakeConst.Test.csproj b/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst.Test/MakeConst.Test.csproj index fa701c81139..4b8d5542696 100644 --- a/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst.Test/MakeConst.Test.csproj +++ b/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst.Test/MakeConst.Test.csproj @@ -8,10 +8,10 @@ - + - + diff --git a/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/MakeConst.csproj b/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/MakeConst.csproj index 4951a18ef71..096ff3e42f4 100644 --- a/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/MakeConst.csproj +++ b/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/MakeConst.csproj @@ -10,7 +10,7 @@ - + diff --git a/csharp/safe-efficient-code/benchmark/benchmark.csproj b/csharp/safe-efficient-code/benchmark/benchmark.csproj index ce879d90ecc..daccd0b2ce8 100644 --- a/csharp/safe-efficient-code/benchmark/benchmark.csproj +++ b/csharp/safe-efficient-code/benchmark/benchmark.csproj @@ -7,7 +7,7 @@ - + diff --git a/csharp/tutorials/AsyncStreams/finished/IssuePRreport/IssuePRreport/IssuePRreport.csproj b/csharp/tutorials/AsyncStreams/finished/IssuePRreport/IssuePRreport/IssuePRreport.csproj index 57017cbf9b9..3f8391d5d1b 100644 --- a/csharp/tutorials/AsyncStreams/finished/IssuePRreport/IssuePRreport/IssuePRreport.csproj +++ b/csharp/tutorials/AsyncStreams/finished/IssuePRreport/IssuePRreport/IssuePRreport.csproj @@ -8,7 +8,7 @@ - + diff --git a/csharp/tutorials/AsyncStreams/start/IssuePRreport/IssuePRreport/IssuePRreport.csproj b/csharp/tutorials/AsyncStreams/start/IssuePRreport/IssuePRreport/IssuePRreport.csproj index 80f78bd1a7d..896aeca01c6 100644 --- a/csharp/tutorials/AsyncStreams/start/IssuePRreport/IssuePRreport/IssuePRreport.csproj +++ b/csharp/tutorials/AsyncStreams/start/IssuePRreport/IssuePRreport/IssuePRreport.csproj @@ -8,7 +8,7 @@ - + diff --git a/csharp/tutorials/nullable-reference-migration/finished/SimpleFeedReader.Tests/SimpleFeedReader.Tests.csproj b/csharp/tutorials/nullable-reference-migration/finished/SimpleFeedReader.Tests/SimpleFeedReader.Tests.csproj index 41e50a0a918..a29862c8de3 100644 --- a/csharp/tutorials/nullable-reference-migration/finished/SimpleFeedReader.Tests/SimpleFeedReader.Tests.csproj +++ b/csharp/tutorials/nullable-reference-migration/finished/SimpleFeedReader.Tests/SimpleFeedReader.Tests.csproj @@ -5,10 +5,10 @@ false - - - - + + + + diff --git a/csharp/tutorials/nullable-reference-migration/start/SimpleFeedReader.Tests/SimpleFeedReader.Tests.csproj b/csharp/tutorials/nullable-reference-migration/start/SimpleFeedReader.Tests/SimpleFeedReader.Tests.csproj index ba47f392983..8e951c89086 100644 --- a/csharp/tutorials/nullable-reference-migration/start/SimpleFeedReader.Tests/SimpleFeedReader.Tests.csproj +++ b/csharp/tutorials/nullable-reference-migration/start/SimpleFeedReader.Tests/SimpleFeedReader.Tests.csproj @@ -4,10 +4,10 @@ false - - - - + + + + diff --git a/csharp/unit-testing-best-practices/after/unit-testing-best-practices-after.csproj b/csharp/unit-testing-best-practices/after/unit-testing-best-practices-after.csproj index 55e7a5ed481..b09d71124e5 100644 --- a/csharp/unit-testing-best-practices/after/unit-testing-best-practices-after.csproj +++ b/csharp/unit-testing-best-practices/after/unit-testing-best-practices-after.csproj @@ -7,9 +7,9 @@ - - - + + + diff --git a/csharp/unit-testing-best-practices/before/unit-testing-best-practices-before.csproj b/csharp/unit-testing-best-practices/before/unit-testing-best-practices-before.csproj index 55e7a5ed481..d17b2e00a16 100644 --- a/csharp/unit-testing-best-practices/before/unit-testing-best-practices-before.csproj +++ b/csharp/unit-testing-best-practices/before/unit-testing-best-practices-before.csproj @@ -7,9 +7,9 @@ - - - + + + diff --git a/csharp/unit-testing-code-coverage/XUnit.Coverlet.Collector/XUnit.Coverlet.Collector.csproj b/csharp/unit-testing-code-coverage/XUnit.Coverlet.Collector/XUnit.Coverlet.Collector.csproj index ee424faf19e..b413b59e64d 100644 --- a/csharp/unit-testing-code-coverage/XUnit.Coverlet.Collector/XUnit.Coverlet.Collector.csproj +++ b/csharp/unit-testing-code-coverage/XUnit.Coverlet.Collector/XUnit.Coverlet.Collector.csproj @@ -7,10 +7,10 @@ - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/csharp/unit-testing-code-coverage/XUnit.Coverlet.MSBuild/XUnit.Coverlet.MSBuild.csproj b/csharp/unit-testing-code-coverage/XUnit.Coverlet.MSBuild/XUnit.Coverlet.MSBuild.csproj index de2a7670bdf..62ee111d126 100644 --- a/csharp/unit-testing-code-coverage/XUnit.Coverlet.MSBuild/XUnit.Coverlet.MSBuild.csproj +++ b/csharp/unit-testing-code-coverage/XUnit.Coverlet.MSBuild/XUnit.Coverlet.MSBuild.csproj @@ -11,9 +11,9 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/csharp/unit-testing/MSTest.Project/MSTest.Project.csproj b/csharp/unit-testing/MSTest.Project/MSTest.Project.csproj index d519ced66a3..18da803d946 100644 --- a/csharp/unit-testing/MSTest.Project/MSTest.Project.csproj +++ b/csharp/unit-testing/MSTest.Project/MSTest.Project.csproj @@ -7,7 +7,7 @@ - + diff --git a/csharp/unit-testing/NUnit.TestProject/NUnit.Project.csproj b/csharp/unit-testing/NUnit.TestProject/NUnit.Project.csproj index d14da773a29..a43a29ea716 100644 --- a/csharp/unit-testing/NUnit.TestProject/NUnit.Project.csproj +++ b/csharp/unit-testing/NUnit.TestProject/NUnit.Project.csproj @@ -7,9 +7,9 @@ - + - + diff --git a/csharp/unit-testing/XUnit.TestProject/XUnit.Project.csproj b/csharp/unit-testing/XUnit.TestProject/XUnit.Project.csproj index 28b5dbece02..1f20b39bb72 100644 --- a/csharp/unit-testing/XUnit.TestProject/XUnit.Project.csproj +++ b/csharp/unit-testing/XUnit.TestProject/XUnit.Project.csproj @@ -7,9 +7,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/framework/libraries/migrate-library-csproj-keep-existing/src/Car.Net45/Car.Net45.csproj b/framework/libraries/migrate-library-csproj-keep-existing/src/Car.Net45/Car.Net45.csproj index 023e99a346b..850fa3e9609 100644 --- a/framework/libraries/migrate-library-csproj-keep-existing/src/Car.Net45/Car.Net45.csproj +++ b/framework/libraries/migrate-library-csproj-keep-existing/src/Car.Net45/Car.Net45.csproj @@ -16,6 +16,6 @@ - + \ No newline at end of file diff --git a/framework/libraries/migrate-library-csproj-keep-existing/src/Car.Net45/packages.config b/framework/libraries/migrate-library-csproj-keep-existing/src/Car.Net45/packages.config index 07af911ca65..b915ec57974 100644 --- a/framework/libraries/migrate-library-csproj-keep-existing/src/Car.Net45/packages.config +++ b/framework/libraries/migrate-library-csproj-keep-existing/src/Car.Net45/packages.config @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/framework/libraries/migrate-library-csproj-keep-existing/tests/Car.Tests.Net45/Car.Tests.Net45.csproj b/framework/libraries/migrate-library-csproj-keep-existing/tests/Car.Tests.Net45/Car.Tests.Net45.csproj index 60c0ff3654f..fb55bc95887 100644 --- a/framework/libraries/migrate-library-csproj-keep-existing/tests/Car.Tests.Net45/Car.Tests.Net45.csproj +++ b/framework/libraries/migrate-library-csproj-keep-existing/tests/Car.Tests.Net45/Car.Tests.Net45.csproj @@ -20,13 +20,13 @@ - + - - - - - - + + + + + + \ No newline at end of file diff --git a/framework/libraries/migrate-library-csproj-keep-existing/tests/Car.Tests.Net45/packages.config b/framework/libraries/migrate-library-csproj-keep-existing/tests/Car.Tests.Net45/packages.config index e8a1fbe198c..29347b426a2 100644 --- a/framework/libraries/migrate-library-csproj-keep-existing/tests/Car.Tests.Net45/packages.config +++ b/framework/libraries/migrate-library-csproj-keep-existing/tests/Car.Tests.Net45/packages.config @@ -1,11 +1,11 @@ - + - - - - - - + + + + + + \ No newline at end of file diff --git a/framework/libraries/migrate-library-csproj-keep-existing/tests/Car.Tests/Car.Tests.csproj b/framework/libraries/migrate-library-csproj-keep-existing/tests/Car.Tests/Car.Tests.csproj index 901768fee6c..5ff75a0a13b 100644 --- a/framework/libraries/migrate-library-csproj-keep-existing/tests/Car.Tests/Car.Tests.csproj +++ b/framework/libraries/migrate-library-csproj-keep-existing/tests/Car.Tests/Car.Tests.csproj @@ -9,8 +9,8 @@ - + - + diff --git a/framework/libraries/migrate-library-csproj/tests/Car.Tests/Car.Tests.csproj b/framework/libraries/migrate-library-csproj/tests/Car.Tests/Car.Tests.csproj index a62addc0240..82f84df44ed 100644 --- a/framework/libraries/migrate-library-csproj/tests/Car.Tests/Car.Tests.csproj +++ b/framework/libraries/migrate-library-csproj/tests/Car.Tests/Car.Tests.csproj @@ -9,9 +9,9 @@ - + - - + + diff --git a/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/App.config b/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/App.config index 7c24503ac7e..b183bdf3249 100644 --- a/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/App.config +++ b/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/App.config @@ -20,5 +20,4 @@ - - + diff --git a/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/CalculatorClientConstructor.cs b/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/CalculatorClientConstructor.cs new file mode 100644 index 00000000000..43fdfba3c04 --- /dev/null +++ b/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/CalculatorClientConstructor.cs @@ -0,0 +1,12 @@ +namespace Microsoft.Samples.TransportSecurity +{ + // This partial class constructor is needed as the service is hosted in IIS and advertises both HTTP and HTTPS endpoints. + // This causes the generated client to have 2 configurations so a default constructor can't be generated as it's unknown which to use. + // By adding this constructor, we can choose which endpoint we wish to use as the default. + public partial class CalculatorClient + { +#if NET6_0_OR_GREATER + public CalculatorClient() : this(EndpointConfiguration.BasicHttpBinding_ICalculator1) { } +#endif + } +} diff --git a/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/Connected Services/Microsoft.Samples.TransportSecurity/ConnectedService.json b/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/Connected Services/Microsoft.Samples.TransportSecurity/ConnectedService.json new file mode 100644 index 00000000000..e6e4df05046 --- /dev/null +++ b/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/Connected Services/Microsoft.Samples.TransportSecurity/ConnectedService.json @@ -0,0 +1,17 @@ +{ + "ExtendedData": { + "inputs": [ + "https://localhost/servicemodelsamples/service.svc" + ], + "collectionTypes": [ + "System.Array", + "System.Collections.Generic.Dictionary`2" + ], + "namespaceMappings": [ + "*, Microsoft.Samples.TransportSecurity" + ], + "sync": true, + "targetFramework": "net6.0", + "typeReuseMode": "None" + } +} \ No newline at end of file diff --git a/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/Connected Services/Microsoft.Samples.TransportSecurity/Reference.cs b/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/Connected Services/Microsoft.Samples.TransportSecurity/Reference.cs new file mode 100644 index 00000000000..b663e8a60d9 --- /dev/null +++ b/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/Connected Services/Microsoft.Samples.TransportSecurity/Reference.cs @@ -0,0 +1,177 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.Samples.TransportSecurity +{ + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.1.0")] + [System.ServiceModel.ServiceContractAttribute(Namespace="http://Microsoft.Samples.TransportSecurity", ConfigurationName="Microsoft.Samples.TransportSecurity.ICalculator")] + public interface ICalculator + { + + [System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.Samples.TransportSecurity/ICalculator/Add", ReplyAction="http://Microsoft.Samples.TransportSecurity/ICalculator/AddResponse")] + double Add(double n1, double n2); + + [System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.Samples.TransportSecurity/ICalculator/Add", ReplyAction="http://Microsoft.Samples.TransportSecurity/ICalculator/AddResponse")] + System.Threading.Tasks.Task AddAsync(double n1, double n2); + + [System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.Samples.TransportSecurity/ICalculator/Subtract", ReplyAction="http://Microsoft.Samples.TransportSecurity/ICalculator/SubtractResponse")] + double Subtract(double n1, double n2); + + [System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.Samples.TransportSecurity/ICalculator/Subtract", ReplyAction="http://Microsoft.Samples.TransportSecurity/ICalculator/SubtractResponse")] + System.Threading.Tasks.Task SubtractAsync(double n1, double n2); + + [System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.Samples.TransportSecurity/ICalculator/Multiply", ReplyAction="http://Microsoft.Samples.TransportSecurity/ICalculator/MultiplyResponse")] + double Multiply(double n1, double n2); + + [System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.Samples.TransportSecurity/ICalculator/Multiply", ReplyAction="http://Microsoft.Samples.TransportSecurity/ICalculator/MultiplyResponse")] + System.Threading.Tasks.Task MultiplyAsync(double n1, double n2); + + [System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.Samples.TransportSecurity/ICalculator/Divide", ReplyAction="http://Microsoft.Samples.TransportSecurity/ICalculator/DivideResponse")] + double Divide(double n1, double n2); + + [System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.Samples.TransportSecurity/ICalculator/Divide", ReplyAction="http://Microsoft.Samples.TransportSecurity/ICalculator/DivideResponse")] + System.Threading.Tasks.Task DivideAsync(double n1, double n2); + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.1.0")] + public interface ICalculatorChannel : Microsoft.Samples.TransportSecurity.ICalculator, System.ServiceModel.IClientChannel + { + } + + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.1.0")] + public partial class CalculatorClient : System.ServiceModel.ClientBase, Microsoft.Samples.TransportSecurity.ICalculator + { + + /// + /// Implement this partial method to configure the service endpoint. + /// + /// The endpoint to configure + /// The client credentials + static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials); + + public CalculatorClient(EndpointConfiguration endpointConfiguration) : + base(CalculatorClient.GetBindingForEndpoint(endpointConfiguration), CalculatorClient.GetEndpointAddress(endpointConfiguration)) + { + this.Endpoint.Name = endpointConfiguration.ToString(); + ConfigureEndpoint(this.Endpoint, this.ClientCredentials); + } + + public CalculatorClient(EndpointConfiguration endpointConfiguration, string remoteAddress) : + base(CalculatorClient.GetBindingForEndpoint(endpointConfiguration), new System.ServiceModel.EndpointAddress(remoteAddress)) + { + this.Endpoint.Name = endpointConfiguration.ToString(); + ConfigureEndpoint(this.Endpoint, this.ClientCredentials); + } + + public CalculatorClient(EndpointConfiguration endpointConfiguration, System.ServiceModel.EndpointAddress remoteAddress) : + base(CalculatorClient.GetBindingForEndpoint(endpointConfiguration), remoteAddress) + { + this.Endpoint.Name = endpointConfiguration.ToString(); + ConfigureEndpoint(this.Endpoint, this.ClientCredentials); + } + + public CalculatorClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : + base(binding, remoteAddress) + { + } + + public double Add(double n1, double n2) + { + return base.Channel.Add(n1, n2); + } + + public System.Threading.Tasks.Task AddAsync(double n1, double n2) + { + return base.Channel.AddAsync(n1, n2); + } + + public double Subtract(double n1, double n2) + { + return base.Channel.Subtract(n1, n2); + } + + public System.Threading.Tasks.Task SubtractAsync(double n1, double n2) + { + return base.Channel.SubtractAsync(n1, n2); + } + + public double Multiply(double n1, double n2) + { + return base.Channel.Multiply(n1, n2); + } + + public System.Threading.Tasks.Task MultiplyAsync(double n1, double n2) + { + return base.Channel.MultiplyAsync(n1, n2); + } + + public double Divide(double n1, double n2) + { + return base.Channel.Divide(n1, n2); + } + + public System.Threading.Tasks.Task DivideAsync(double n1, double n2) + { + return base.Channel.DivideAsync(n1, n2); + } + + public virtual System.Threading.Tasks.Task OpenAsync() + { + return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action(((System.ServiceModel.ICommunicationObject)(this)).EndOpen)); + } + + private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration) + { + if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_ICalculator)) + { + System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding(); + result.MaxBufferSize = int.MaxValue; + result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max; + result.MaxReceivedMessageSize = int.MaxValue; + result.AllowCookies = true; + return result; + } + if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_ICalculator1)) + { + System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding(); + result.MaxBufferSize = int.MaxValue; + result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max; + result.MaxReceivedMessageSize = int.MaxValue; + result.AllowCookies = true; + result.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.Transport; + return result; + } + throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration)); + } + + private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration) + { + if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_ICalculator)) + { + return new System.ServiceModel.EndpointAddress("http://localhost/servicemodelsamples/service.svc"); + } + if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_ICalculator1)) + { + return new System.ServiceModel.EndpointAddress("https://localhost/servicemodelsamples/service.svc"); + } + throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration)); + } + + public enum EndpointConfiguration + { + + BasicHttpBinding_ICalculator, + + BasicHttpBinding_ICalculator1, + } + } +} diff --git a/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/Properties/AssemblyInfo.cs b/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/Properties/AssemblyInfo.cs deleted file mode 100644 index 921c832801c..00000000000 --- a/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: ComVisible(false)] -[assembly: CLSCompliant(true)] -[assembly: AssemblyTitle("Client")] -[assembly: AssemblyDescription("TransportSecurity")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft Corporation")] -[assembly: AssemblyProduct("Windows Communication Foundation and Windows Workflow Foundation SDK")] -[assembly: AssemblyCopyright("Copyright (c) Microsoft Corporation")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("4.0.0.0")] -[assembly: AssemblyFileVersion("4.0.0.0")] \ No newline at end of file diff --git a/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/client.cs b/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/client.cs index f26c6a40577..ee359cdd20d 100644 --- a/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/client.cs +++ b/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/client.cs @@ -3,8 +3,10 @@ //---------------------------------------------------------------- using System; -using System.Net; +using System.IdentityModel.Selectors; +using System.IdentityModel.Tokens; using System.Security.Cryptography.X509Certificates; +using System.ServiceModel.Security; namespace Microsoft.Samples.TransportSecurity { @@ -17,10 +19,12 @@ static void Main() { // WARNING: This code is only needed for test certificates such as those created by makecert. It is // not recommended for production code. - PermissiveCertificatePolicy.Enact("CN=ServiceModelSamples-HTTPS-Server"); - // Create a client CalculatorClient client = new CalculatorClient(); + client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication(); + client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication.CertificateValidationMode = X509CertificateValidationMode.Custom; + MyX509CertificateValidator myX509CertificateValidator = new MyX509CertificateValidator("CN=ServiceModelSamples-HTTPS-Server"); + client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication.CustomCertificateValidator = myX509CertificateValidator; // Call the Add service operation. double value1 = 100.00D; @@ -57,30 +61,34 @@ static void Main() // WARNING: This code is only needed for test certificates such as those created by makecert. It is // not recommended for production code. - class PermissiveCertificatePolicy + public class MyX509CertificateValidator : X509CertificateValidator { - string subjectName; - static PermissiveCertificatePolicy currentPolicy; - PermissiveCertificatePolicy(string subjectName) - { - this.subjectName = subjectName; - ServicePointManager.ServerCertificateValidationCallback += - new System.Net.Security.RemoteCertificateValidationCallback(RemoteCertValidate); - } + private string _allowedIssuerName; - public static void Enact(string subjectName) + public MyX509CertificateValidator(string allowedIssuerName) { - currentPolicy = new PermissiveCertificatePolicy(subjectName); + if (string.IsNullOrEmpty(allowedIssuerName)) + { + throw new ArgumentNullException("allowedIssuerName", "[MyX509CertificateValidator] The string parameter allowedIssuerName was null or empty."); + } + + _allowedIssuerName = allowedIssuerName; } - bool RemoteCertValidate(object sender, X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error) + public override void Validate(X509Certificate2 certificate) { - if (cert.Subject == subjectName) + // Check that there is a certificate. + if (certificate == null) { - return true; + throw new ArgumentNullException("certificate", "[MyX509CertificateValidator] The X509Certificate2 parameter certificate was null."); } - return false; + // Check that the certificate issuer matches the configured issuer. + if (!certificate.Subject.Contains(_allowedIssuerName)) + { + throw new SecurityTokenValidationException + (string.Format("Certificate was not issued by a trusted issuer. Expected: {0}, Actual: {1}", _allowedIssuerName, certificate.IssuerName.Name)); + } } } } diff --git a/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/client.csproj b/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/client.csproj index 8dea0376b96..37c20b32c17 100644 --- a/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/client.csproj +++ b/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/client/client.csproj @@ -1,96 +1,34 @@ - - + - Debug - AnyCPU - 8.0.50301 - 2.0 - {F6D8FC2E-62D0-4554-AC3E-1964042590E3} + net462;net6.0 Exe - Properties - - - client - v4.8 - - - 2.0 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - + Client + TransportSecurity + Microsoft Corporation + Windows Communication Foundation and Windows Workflow Foundation SDK + Copyright (c) Microsoft Corporation - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - false - - - pdbonly - true - bin\ - TRACE - prompt - 4 - AllRules.ruleset - false - - - - - - - - + + + + + - - - - + + + + + - - + + + + - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Microsoft Visual Basic PowerPacks 10.0 - true - - - False - Windows Installer 3.1 - true - + + + + - - \ No newline at end of file + + diff --git a/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/service/service.csproj b/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/service/service.csproj index d613975c62e..94b0854c98c 100644 --- a/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/service/service.csproj +++ b/framework/wcf/Basic/Binding/Basic/TransportSecurity/CS/service/service.csproj @@ -1,37 +1,16 @@  - + + Debug AnyCPU 8.0.50110 - 2.0 {73D6E51B-9EAB-4EBE-BAA3-794D636BD176} Library Properties - - service - v4.8 - - - 2.0 - + v4.6.2 publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - true @@ -70,34 +49,14 @@ - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Microsoft Visual Basic PowerPacks 10.0 - true - - - False - Windows Installer 3.1 - true - - - - if not exist %25SystemDrive%25\inetpub\wwwroot\servicemodelsamples\bin mkdir %25SystemDrive%25\inetpub\wwwroot\servicemodelsamples\bin - copy "$(ProjectDir)Service.svc" %25SystemDrive%25\inetpub\wwwroot\servicemodelsamples\ - copy "$(TargetDir)*.dll" %25SystemDrive%25\inetpub\wwwroot\servicemodelsamples\bin - copy "$(ProjectDir)Web.config" %25SystemDrive%25\inetpub\wwwroot\servicemodelsamples - copy "$(TargetDir)Service.pdb" %25SystemDrive%25\inetpub\wwwroot\servicemodelsamples\bin + + if not exist %SystemDrive%\inetpub\wwwroot\servicemodelsamples\bin mkdir %SystemDrive%\inetpub\wwwroot\servicemodelsamples\bin + copy "$(MSBuildProjectDirectory)\Service.svc" %SystemDrive%\inetpub\wwwroot\servicemodelsamples\ + copy "$(TargetDir)Service.dll" %SystemDrive%\inetpub\wwwroot\servicemodelsamples\bin + copy "$(MSBuildProjectDirectory)\Web.config" %SystemDrive%\inetpub\wwwroot\servicemodelsamples + copy "$(TargetDir)Service.pdb" %SystemDrive%\inetpub\wwwroot\servicemodelsamples\bin + - \ No newline at end of file + + diff --git a/framework/wcf/Basic/Binding/Net/Tcp/Default/CS/client/client.cs b/framework/wcf/Basic/Binding/Net/Tcp/Default/CS/client/client.cs index 39817905c53..74751c83cee 100644 --- a/framework/wcf/Basic/Binding/Net/Tcp/Default/CS/client/client.cs +++ b/framework/wcf/Basic/Binding/Net/Tcp/Default/CS/client/client.cs @@ -3,12 +3,13 @@ //---------------------------------------------------------------- using System; +using System.ServiceModel; namespace Microsoft.Samples.NetTcp { - //The service contract is defined in generatedClient.cs, generated from the service by the svcutil tool. + // The service contract is defined in generatedClient.cs, generated from the service by the svcutil tool. - //Client implementation code. + // Client implementation code. class Client { static void Main() @@ -16,6 +17,12 @@ static void Main() // Create a client CalculatorClient client = new CalculatorClient(); + // Include the identity element when running cross-machine in a domain. + // NetTcpBinding binding = new NetTcpBinding(); + // var endpointIdentity = new UpnEndpointIdentity("user_name@service_domain"); + // EndpointAddress endpointAddress = new EndpointAddress(new Uri("net.tcp://localhost:9000/servicemodelsamples/service"), endpointIdentity); + // CalculatorClient client = new CalculatorClient(binding, endpointAddress); + // Call the Add service operation. double value1 = 100.00D; double value2 = 15.99D; diff --git a/framework/wcf/Basic/Binding/Net/Tcp/Default/CS/client/client.csproj b/framework/wcf/Basic/Binding/Net/Tcp/Default/CS/client/client.csproj index aba46583692..4d8e291c24a 100644 --- a/framework/wcf/Basic/Binding/Net/Tcp/Default/CS/client/client.csproj +++ b/framework/wcf/Basic/Binding/Net/Tcp/Default/CS/client/client.csproj @@ -22,6 +22,7 @@ + @@ -31,4 +32,3 @@ - diff --git a/github-actions/DotNet.GitHubAction/CODE_METRICS.md b/github-actions/DotNet.GitHubAction/CODE_METRICS.md index b777e60213d..eb399b7c393 100644 --- a/github-actions/DotNet.GitHubAction/CODE_METRICS.md +++ b/github-actions/DotNet.GitHubAction/CODE_METRICS.md @@ -598,14 +598,14 @@ The *DotNet.GitHubAction.csproj* project file contains: - 4 namespaces. - 6 named types. -- 669 total lines of source code. -- Approximately 288 lines of executable code. +- 685 total lines of source code. +- Approximately 304 lines of executable code. - The highest cyclomatic complexity is 13 :x:.
- <global namespace> :heavy_check_mark: + <global namespace> :warning:
@@ -613,26 +613,26 @@ The *DotNet.GitHubAction.csproj* project file contains: The `` namespace contains 1 named types. - 1 named types. -- 94 total lines of source code. -- Approximately 94 lines of executable code. -- The highest cyclomatic complexity is 7 :heavy_check_mark:. +- 110 total lines of source code. +- Approximately 110 lines of executable code. +- The highest cyclomatic complexity is 8 :warning:.
- <Program>$ :heavy_check_mark: + <Program>$ :warning:
- The `$` contains 1 members. -- 94 total lines of source code. -- Approximately 94 lines of executable code. -- The highest cyclomatic complexity is 7 :heavy_check_mark:. +- 110 total lines of source code. +- Approximately 110 lines of executable code. +- The highest cyclomatic complexity is 8 :warning:. | Member kind | Line number | Maintainability index | Cyclomatic complexity | Depth of inheritance | Class coupling | Lines of source / executable code | | :-: | :-: | :-: | :-: | :-: | :-: | :-: | -| Method | 1 | 42 | 7 :heavy_check_mark: | 0 | 15 | 94 / 47 | +| Method | 1 | 40 | 8 :warning: | 0 | 16 | 110 / 55 | :top: back to <global namespace> diff --git a/github-actions/DotNet.GitHubAction/DotNet.GitHubAction/Program.cs b/github-actions/DotNet.GitHubAction/DotNet.GitHubAction/Program.cs index a63f5c91627..4590069c45b 100644 --- a/github-actions/DotNet.GitHubAction/DotNet.GitHubAction/Program.cs +++ b/github-actions/DotNet.GitHubAction/DotNet.GitHubAction/Program.cs @@ -79,7 +79,9 @@ await File.WriteAllTextAsync( { textWriter.WriteLine($"updated-metrics={updatedMetrics}"); textWriter.WriteLine($"summary-title={title}"); - textWriter.WriteLine($"summary-details={summary}"); + textWriter.WriteLine("summary-details< - + diff --git a/machine-learning/tutorials/IrisFlowerClustering/IrisFlowerClustering.csproj b/machine-learning/tutorials/IrisFlowerClustering/IrisFlowerClustering.csproj index 70038d55b2e..c22f52e0969 100644 --- a/machine-learning/tutorials/IrisFlowerClustering/IrisFlowerClustering.csproj +++ b/machine-learning/tutorials/IrisFlowerClustering/IrisFlowerClustering.csproj @@ -6,7 +6,7 @@ - + diff --git a/machine-learning/tutorials/MovieRecommendation/MovieRecommendation.csproj b/machine-learning/tutorials/MovieRecommendation/MovieRecommendation.csproj index d4a9446042f..00fc036e0b7 100644 --- a/machine-learning/tutorials/MovieRecommendation/MovieRecommendation.csproj +++ b/machine-learning/tutorials/MovieRecommendation/MovieRecommendation.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/machine-learning/tutorials/ProductSalesAnomalyDetection/ProductSalesAnomalyDetection.csproj b/machine-learning/tutorials/ProductSalesAnomalyDetection/ProductSalesAnomalyDetection.csproj index 94f4515a2fa..663ab102a45 100644 --- a/machine-learning/tutorials/ProductSalesAnomalyDetection/ProductSalesAnomalyDetection.csproj +++ b/machine-learning/tutorials/ProductSalesAnomalyDetection/ProductSalesAnomalyDetection.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/machine-learning/tutorials/SentimentAnalysis/SentimentAnalysis.csproj b/machine-learning/tutorials/SentimentAnalysis/SentimentAnalysis.csproj index 256c798f734..ab1e32e61ec 100644 --- a/machine-learning/tutorials/SentimentAnalysis/SentimentAnalysis.csproj +++ b/machine-learning/tutorials/SentimentAnalysis/SentimentAnalysis.csproj @@ -10,7 +10,7 @@ - + diff --git a/machine-learning/tutorials/TaxiFarePrediction/TaxiFarePrediction.csproj b/machine-learning/tutorials/TaxiFarePrediction/TaxiFarePrediction.csproj index 98a9ce97ab5..8a7c4a583fb 100644 --- a/machine-learning/tutorials/TaxiFarePrediction/TaxiFarePrediction.csproj +++ b/machine-learning/tutorials/TaxiFarePrediction/TaxiFarePrediction.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/machine-learning/tutorials/TextClassificationTF/TextClassificationTF.csproj b/machine-learning/tutorials/TextClassificationTF/TextClassificationTF.csproj index 65d5343938b..25051b4dbf5 100644 --- a/machine-learning/tutorials/TextClassificationTF/TextClassificationTF.csproj +++ b/machine-learning/tutorials/TextClassificationTF/TextClassificationTF.csproj @@ -6,10 +6,10 @@ - - - - + + + + diff --git a/machine-learning/tutorials/TransferLearningTF/TransferLearningTF.csproj b/machine-learning/tutorials/TransferLearningTF/TransferLearningTF.csproj index d3e5f207664..a5a1aed8183 100644 --- a/machine-learning/tutorials/TransferLearningTF/TransferLearningTF.csproj +++ b/machine-learning/tutorials/TransferLearningTF/TransferLearningTF.csproj @@ -7,10 +7,10 @@ - - - - + + + + diff --git a/mef/simple-calculator/vb/MefCalculator/MefCalculator.vbproj b/mef/simple-calculator/vb/MefCalculator/MefCalculator.vbproj index 61b4297f522..90bfd5d1be2 100644 --- a/mef/simple-calculator/vb/MefCalculator/MefCalculator.vbproj +++ b/mef/simple-calculator/vb/MefCalculator/MefCalculator.vbproj @@ -1,4 +1,4 @@ - + MefCalculator @@ -6,7 +6,7 @@ - + diff --git a/mef/simple-calculator/vb/SimpleCalculator2.vbproj b/mef/simple-calculator/vb/SimpleCalculator2.vbproj index 26a480b3ece..ff84ad2e6c6 100644 --- a/mef/simple-calculator/vb/SimpleCalculator2.vbproj +++ b/mef/simple-calculator/vb/SimpleCalculator2.vbproj @@ -1,4 +1,4 @@ - + Exe @@ -26,7 +26,7 @@ - + diff --git a/orleans/ShoppingCart/Silo/Orleans.ShoppingCart.Silo.csproj b/orleans/ShoppingCart/Silo/Orleans.ShoppingCart.Silo.csproj index 3c4b91cca9f..32e8a4ec576 100644 --- a/orleans/ShoppingCart/Silo/Orleans.ShoppingCart.Silo.csproj +++ b/orleans/ShoppingCart/Silo/Orleans.ShoppingCart.Silo.csproj @@ -1,4 +1,4 @@ - + net8.0 diff --git a/windowsforms/datagridview/CSWinFormDataGridView/CSWinFormDataGridView.csproj b/windowsforms/datagridview/CSWinFormDataGridView/CSWinFormDataGridView.csproj index 95632375862..3b1cbe1ca0b 100644 --- a/windowsforms/datagridview/CSWinFormDataGridView/CSWinFormDataGridView.csproj +++ b/windowsforms/datagridview/CSWinFormDataGridView/CSWinFormDataGridView.csproj @@ -13,7 +13,7 @@ - +