From e479ac52a07ffb8a33e0a931e2444a55333c36b1 Mon Sep 17 00:00:00 2001 From: Rolling2405 <89894749+Rolling2405@users.noreply.github.com> Date: Fri, 27 Mar 2026 11:23:04 -0700 Subject: [PATCH 01/13] Modernize for .NET 10: add net10.0 target and convert DllImport to LibraryImport (#283) --- .github/workflows/CI.yml | 7 +++++- src/Microsoft.Dism/DismApi.AddCapability.cs | 7 +++++- src/Microsoft.Dism/DismApi.AddDriver.cs | 7 +++++- src/Microsoft.Dism/DismApi.AddPackage.cs | 7 +++++- .../DismApi.AddProvisionedAppxPackage.cs | 25 ++++++++++++++++++- src/Microsoft.Dism/DismApi.ApplyFfuImage.cs | 7 +++++- src/Microsoft.Dism/DismApi.ApplyUnattend.cs | 7 +++++- .../DismApi.CheckImageHealth.cs | 7 +++++- .../DismApi.CleanupMountpoints.cs | 7 +++++- src/Microsoft.Dism/DismApi.CloseSession.cs | 7 +++++- src/Microsoft.Dism/DismApi.CommitImage.cs | 7 +++++- src/Microsoft.Dism/DismApi.Delete.cs | 7 +++++- src/Microsoft.Dism/DismApi.DisableFeature.cs | 7 +++++- src/Microsoft.Dism/DismApi.EnableFeature.cs | 7 +++++- src/Microsoft.Dism/DismApi.GetCapabilities.cs | 7 +++++- .../DismApi.GetCapabilityInfo.cs | 7 +++++- .../DismApi.GetCurrentEdition.cs | 7 +++++- src/Microsoft.Dism/DismApi.GetDriverInfo.cs | 7 +++++- src/Microsoft.Dism/DismApi.GetDrivers.cs | 7 +++++- src/Microsoft.Dism/DismApi.GetFeatureInfo.cs | 7 +++++- .../DismApi.GetFeatureParent.cs | 7 +++++- src/Microsoft.Dism/DismApi.GetFeatures.cs | 7 +++++- src/Microsoft.Dism/DismApi.GetImageInfo.cs | 7 +++++- .../DismApi.GetLastErrorMessage.cs | 7 +++++- .../DismApi.GetMountedImages.cs | 7 +++++- src/Microsoft.Dism/DismApi.GetPackageInfo.cs | 7 +++++- .../DismApi.GetPackageInfoEx.cs | 7 +++++- src/Microsoft.Dism/DismApi.GetPackages.cs | 7 +++++- .../DismApi.GetProductKeyInfo.cs | 7 +++++- .../DismApi.GetProvisionedAppxPackages.cs | 7 +++++- .../DismApi.GetRegistryMountPoint.cs | 7 +++++- .../DismApi.GetTargetEditions.cs | 7 +++++- src/Microsoft.Dism/DismApi.Initialize.cs | 7 +++++- src/Microsoft.Dism/DismApi.MountImage.cs | 7 +++++- src/Microsoft.Dism/DismApi.NativeMethods.cs | 5 ++++ src/Microsoft.Dism/DismApi.OpenSession.cs | 7 +++++- src/Microsoft.Dism/DismApi.RemountImage.cs | 7 +++++- .../DismApi.RemoveCapability.cs | 7 +++++- src/Microsoft.Dism/DismApi.RemoveDriver.cs | 7 +++++- src/Microsoft.Dism/DismApi.RemovePackage.cs | 7 +++++- .../DismApi.RemoveProvisionedAppxPackage.cs | 7 +++++- .../DismApi.RestoreImageHealth.cs | 7 +++++- src/Microsoft.Dism/DismApi.SetEdition.cs | 13 +++++++++- src/Microsoft.Dism/DismApi.SetProductKey.cs | 7 +++++- src/Microsoft.Dism/DismApi.Shutdown.cs | 7 +++++- src/Microsoft.Dism/DismApi.SplitFfuImage.cs | 7 +++++- src/Microsoft.Dism/DismApi.UnmountImage.cs | 7 +++++- .../DismApi.ValidateProductKey.cs | 7 +++++- src/Microsoft.Dism/DismProgressCallback.cs | 2 ++ src/Microsoft.Dism/DismUtilities.cs | 17 ++++++++++--- src/Microsoft.Dism/Microsoft.Dism.csproj | 5 ++-- 51 files changed, 330 insertions(+), 52 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 947b1ab..103a211 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -16,6 +16,7 @@ env: BuildConfiguration: 'Debug' BuildPlatform: 'Any CPU' ContinuousIntegrationBuild: 'true' + DotNet8Version: '8.x' DotNet10Version: '10.x' jobs: @@ -29,10 +30,11 @@ jobs: with: fetch-depth: 0 - - name: Install .NET ${{ env.DotNet10Version }} + - name: Install .NET ${{ env.DotNet8Version }} and ${{ env.DotNet10Version }} uses: actions/setup-dotnet@v5 with: dotnet-version: | + ${{ env.DotNet8Version }} ${{ env.DotNet10Version }} - name: Build Solution @@ -41,6 +43,9 @@ jobs: - name: Run Unit Tests (.NET Framework) run: dotnet test --no-restore --no-build --framework net472 "/Property:Platform=${{ env.BuildPlatform }};Configuration=${{ env.BuildConfiguration }}" "/BinaryLogger:${{ env.ArtifactsDirectoryName }}/test-net472.binlog" + - name: Run Unit Tests (.NET 8) + run: dotnet test --no-restore --no-build --framework net8.0 "/Property:Platform=${{ env.BuildPlatform }};Configuration=${{ env.BuildConfiguration }}" "/BinaryLogger:${{ env.ArtifactsDirectoryName }}/test-net8.0.binlog" + - name: Run Unit Tests (.NET 10) run: dotnet test --no-restore --no-build --framework net10.0 "/Property:Platform=${{ env.BuildPlatform }};Configuration=${{ env.BuildConfiguration }}" "/BinaryLogger:${{ env.ArtifactsDirectoryName }}/test-net10.0.binlog" diff --git a/src/Microsoft.Dism/DismApi.AddCapability.cs b/src/Microsoft.Dism/DismApi.AddCapability.cs index 5ce4ab3..309688a 100644 --- a/src/Microsoft.Dism/DismApi.AddCapability.cs +++ b/src/Microsoft.Dism/DismApi.AddCapability.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -81,8 +81,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismAddCapability(_In_ DismSession Session, _In_ PCWSTR Name, _In_ BOOL LimitAccess, _In_ PCWSTR* SourcePaths, _In_opt_ UINT SourcePathCount, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismAddCapability(DismSession session, string name, [MarshalAs(UnmanagedType.Bool)] bool limitAccess, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 6)] string[] sourcePaths, UInt32 sourcePathCount, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismAddCapability(DismSession session, string name, [MarshalAs(UnmanagedType.Bool)] bool limitAccess, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 6)] string[] sourcePaths, UInt32 sourcePathCount, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.AddDriver.cs b/src/Microsoft.Dism/DismApi.AddDriver.cs index 112a245..4a2e936 100644 --- a/src/Microsoft.Dism/DismApi.AddDriver.cs +++ b/src/Microsoft.Dism/DismApi.AddDriver.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -53,8 +53,13 @@ internal static partial class NativeMethods /// /// CDATA[HRESULT WINAPI DismAddDriver (_In_ DismSession Session, _In_ PCWSTR DriverPath, _In_ BOOL ForceUnsigned); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismAddDriver(DismSession session, string driverPath, [MarshalAs(UnmanagedType.Bool)] bool forceUnsigned); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismAddDriver(DismSession session, string driverPath, [MarshalAs(UnmanagedType.Bool)] bool forceUnsigned); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.AddPackage.cs b/src/Microsoft.Dism/DismApi.AddPackage.cs index 3da3da4..b492905 100644 --- a/src/Microsoft.Dism/DismApi.AddPackage.cs +++ b/src/Microsoft.Dism/DismApi.AddPackage.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -84,8 +84,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismAddPackage (_In_ DismSession Session, _In_ PCWSTR PackagePath, _In_ BOOL IgnoreCheck, _In_ BOOL PreventPending _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData) /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismAddPackage(DismSession session, string packagePath, [MarshalAs(UnmanagedType.Bool)] bool ignoreCheck, [MarshalAs(UnmanagedType.Bool)] bool preventPending, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismAddPackage(DismSession session, string packagePath, [MarshalAs(UnmanagedType.Bool)] bool ignoreCheck, [MarshalAs(UnmanagedType.Bool)] bool preventPending, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #endif } } } diff --git a/src/Microsoft.Dism/DismApi.AddProvisionedAppxPackage.cs b/src/Microsoft.Dism/DismApi.AddProvisionedAppxPackage.cs index 2fcaab5..25129bc 100644 --- a/src/Microsoft.Dism/DismApi.AddProvisionedAppxPackage.cs +++ b/src/Microsoft.Dism/DismApi.AddProvisionedAppxPackage.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -120,6 +120,28 @@ internal static partial class NativeMethods /// _In_opt_ PCWSTR Region, /// _In_ DismStubPackageOption stubPackageOption); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int _DismAddProvisionedAppxPackage( + DismSession Session, + [MarshalAs(UnmanagedType.LPWStr)] + string AppPath, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 3)] + string[] DependencyPackages, + uint DependencyPackageCount, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 5)] + string[] OptionalPackages, + uint OptionalPackageCount, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 7)] + string[] LicensePaths, + uint LicensePathCount, + [MarshalAs(UnmanagedType.Bool)] bool SkipLicense, + [MarshalAs(UnmanagedType.LPWStr)] + string CustomDataPath, + [MarshalAs(UnmanagedType.LPWStr)] + string? Regions, + DismStubPackageOption stubPackageOption); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int _DismAddProvisionedAppxPackage( DismSession Session, @@ -140,6 +162,7 @@ public static extern int _DismAddProvisionedAppxPackage( [MarshalAs(UnmanagedType.LPWStr)] string? Regions, DismStubPackageOption stubPackageOption); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.ApplyFfuImage.cs b/src/Microsoft.Dism/DismApi.ApplyFfuImage.cs index 7aaa319..6bbb0a1 100644 --- a/src/Microsoft.Dism/DismApi.ApplyFfuImage.cs +++ b/src/Microsoft.Dism/DismApi.ApplyFfuImage.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -38,8 +38,13 @@ internal static partial class NativeMethods /// The drive path to apply the image to. /// An optional file pattern that matches the names of split FFU images. /// Returns S_OK on success. + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int _DismApplyFfuImage([MarshalAs(UnmanagedType.LPWStr)] string ImagePath, [MarshalAs(UnmanagedType.LPWStr)] string ApplyPath, [MarshalAs(UnmanagedType.LPWStr)] string PartPath); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int _DismApplyFfuImage([MarshalAs(UnmanagedType.LPWStr)] string ImagePath, [MarshalAs(UnmanagedType.LPWStr)] string ApplyPath, [MarshalAs(UnmanagedType.LPWStr)] string PartPath); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.ApplyUnattend.cs b/src/Microsoft.Dism/DismApi.ApplyUnattend.cs index d903db0..219e0b6 100644 --- a/src/Microsoft.Dism/DismApi.ApplyUnattend.cs +++ b/src/Microsoft.Dism/DismApi.ApplyUnattend.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -35,8 +35,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismApplyUnattend (_In_ DismSession Session, _In_ PCWSTR UnattendFile, _In_ BOOL SingleSession); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismApplyUnattend(DismSession session, string unattendFile, [MarshalAs(UnmanagedType.Bool)] bool singleSession); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismApplyUnattend(DismSession session, string unattendFile, [MarshalAs(UnmanagedType.Bool)] bool singleSession); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.CheckImageHealth.cs b/src/Microsoft.Dism/DismApi.CheckImageHealth.cs index 3ae2209..bbb2cfe 100644 --- a/src/Microsoft.Dism/DismApi.CheckImageHealth.cs +++ b/src/Microsoft.Dism/DismApi.CheckImageHealth.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -75,8 +75,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismCheckImageHealth(_In_ DismSession Session, _In_ BOOL ScanImage, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData, _Out_ DismImageHealthState* ImageHealth); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismCheckImageHealth(DismSession session, [MarshalAs(UnmanagedType.Bool)] bool scanImage, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData, out DismImageHealthState imageHealth); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismCheckImageHealth(DismSession session, [MarshalAs(UnmanagedType.Bool)] bool scanImage, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData, out DismImageHealthState imageHealth); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.CleanupMountpoints.cs b/src/Microsoft.Dism/DismApi.CleanupMountpoints.cs index b131782..44cc2d9 100644 --- a/src/Microsoft.Dism/DismApi.CleanupMountpoints.cs +++ b/src/Microsoft.Dism/DismApi.CleanupMountpoints.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -28,8 +28,13 @@ internal static partial class NativeMethods /// Returns S_OK on success. /// /// HRESULT WINAPI DismCleanupMountpoints( ); + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismCleanupMountpoints(); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismCleanupMountpoints(); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.CloseSession.cs b/src/Microsoft.Dism/DismApi.CloseSession.cs index 2752b87..f32b035 100644 --- a/src/Microsoft.Dism/DismApi.CloseSession.cs +++ b/src/Microsoft.Dism/DismApi.CloseSession.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -36,8 +36,13 @@ internal static partial class NativeMethods /// The DISMSession will be shut down after this call is completed but the image will not be unmounted. To unmount the image, use the DismUnmountImage Function once all sessions are closed. /// /// HRESULT WINAPI DismCloseSession(_In_ DismSession Session); + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismCloseSession(IntPtr session); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismCloseSession(IntPtr session); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.CommitImage.cs b/src/Microsoft.Dism/DismApi.CommitImage.cs index f7182f8..e260d76 100644 --- a/src/Microsoft.Dism/DismApi.CommitImage.cs +++ b/src/Microsoft.Dism/DismApi.CommitImage.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -73,8 +73,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismCommitImage(_In_ DismSession Session, _In_ DWORD Flags, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismCommitImage(DismSession session, UInt32 flags, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismCommitImage(DismSession session, UInt32 flags, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.Delete.cs b/src/Microsoft.Dism/DismApi.Delete.cs index c7ccbcf..20359d4 100644 --- a/src/Microsoft.Dism/DismApi.Delete.cs +++ b/src/Microsoft.Dism/DismApi.Delete.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -31,8 +31,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismDelete(_In_ VOID* DismStructure); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismDelete(IntPtr dismStructure); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismDelete(IntPtr dismStructure); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.DisableFeature.cs b/src/Microsoft.Dism/DismApi.DisableFeature.cs index 97bcf24..5ec65f1 100644 --- a/src/Microsoft.Dism/DismApi.DisableFeature.cs +++ b/src/Microsoft.Dism/DismApi.DisableFeature.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -87,8 +87,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismDisableFeature (_In_ DismSession Session, _In_ PCWSTR FeatureName, _In_opt_ PCWSTR PackageName, _In_ BOOL RemovePayload, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismDisableFeature(DismSession session, string featureName, string packageName, [MarshalAs(UnmanagedType.Bool)] bool removePayload, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismDisableFeature(DismSession session, string featureName, string packageName, [MarshalAs(UnmanagedType.Bool)] bool removePayload, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.EnableFeature.cs b/src/Microsoft.Dism/DismApi.EnableFeature.cs index 9c9c40d..9288457 100644 --- a/src/Microsoft.Dism/DismApi.EnableFeature.cs +++ b/src/Microsoft.Dism/DismApi.EnableFeature.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -266,8 +266,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismEnableFeature (_In_ DismSession Session, _In_ PCWSTR FeatureName, _In_opt_ PCWSTR Identifier, _In_opt_ DismPackageIdentifier PackageIdentifier, _In_ BOOL LimitAccess, _In_reads_opt_(SourcePathCount) PCWSTR* SourcePaths, _In_opt_ UINT SourcePathCount, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismEnableFeature(DismSession session, string featureName, string? identifier, DismPackageIdentifier packageIdentifier, [MarshalAs(UnmanagedType.Bool)] bool limitAccess, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 6)] string[] sourcePaths, UInt32 sourcePathCount, [MarshalAs(UnmanagedType.Bool)] bool enableAll, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismEnableFeature(DismSession session, string featureName, string? identifier, DismPackageIdentifier packageIdentifier, [MarshalAs(UnmanagedType.Bool)] bool limitAccess, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 6)] string[] sourcePaths, UInt32 sourcePathCount, [MarshalAs(UnmanagedType.Bool)] bool enableAll, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetCapabilities.cs b/src/Microsoft.Dism/DismApi.GetCapabilities.cs index b23325b..f86c0e8 100644 --- a/src/Microsoft.Dism/DismApi.GetCapabilities.cs +++ b/src/Microsoft.Dism/DismApi.GetCapabilities.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -40,8 +40,13 @@ internal static partial class NativeMethods /// Pointer that will receive the info of capability. /// The number of DismCapability structures that were returned. /// Returns S_OK on success. + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismGetCapabilities(DismSession session, out IntPtr capability, out UInt32 count); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismGetCapabilities(DismSession session, out IntPtr capability, out UInt32 count); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetCapabilityInfo.cs b/src/Microsoft.Dism/DismApi.GetCapabilityInfo.cs index 0efff5a..a1b7ebb 100644 --- a/src/Microsoft.Dism/DismApi.GetCapabilityInfo.cs +++ b/src/Microsoft.Dism/DismApi.GetCapabilityInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -43,8 +43,13 @@ internal static partial class NativeMethods /// The name of the specified capability. /// Pointer that will receive the info of capability. /// Returns S_OK on success. + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismGetCapabilityInfo(DismSession session, string name, out IntPtr info); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismGetCapabilityInfo(DismSession session, string name, out IntPtr info); + #endif } } } diff --git a/src/Microsoft.Dism/DismApi.GetCurrentEdition.cs b/src/Microsoft.Dism/DismApi.GetCurrentEdition.cs index 081d8bb..7915c3f 100644 --- a/src/Microsoft.Dism/DismApi.GetCurrentEdition.cs +++ b/src/Microsoft.Dism/DismApi.GetCurrentEdition.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -41,8 +41,13 @@ internal static partial class NativeMethods /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// Recieves a pointer to a structure containing the edition ID of the image. /// Returns S_OK on success. + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, EntryPoint = "_DismGetCurrentEdition")] + public static partial int DismGetCurrentEdition(DismSession session, out IntPtr editionId); + #else [DllImport(DismDllName, EntryPoint = "_DismGetCurrentEdition")] public static extern int DismGetCurrentEdition(DismSession session, out IntPtr editionId); + #endif } } } diff --git a/src/Microsoft.Dism/DismApi.GetDriverInfo.cs b/src/Microsoft.Dism/DismApi.GetDriverInfo.cs index ff3c36c..042eb0f 100644 --- a/src/Microsoft.Dism/DismApi.GetDriverInfo.cs +++ b/src/Microsoft.Dism/DismApi.GetDriverInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -70,8 +70,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismGetDriverInfo (_In_ DismSession Session, _In_ PCWSTR DriverPath, _Outptr_result_buffer_(*Count) DismDriver** Driver, _Out_ UINT* Count, _Out_opt_ DismDriverPackage** DriverPackage); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismGetDriverInfo(DismSession session, string driverPath, out IntPtr driver, out UInt32 count, out IntPtr driverPackage); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismGetDriverInfo(DismSession session, string driverPath, out IntPtr driver, out UInt32 count, out IntPtr driverPackage); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetDrivers.cs b/src/Microsoft.Dism/DismApi.GetDrivers.cs index a61e8dc..92dcd37 100644 --- a/src/Microsoft.Dism/DismApi.GetDrivers.cs +++ b/src/Microsoft.Dism/DismApi.GetDrivers.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -47,8 +47,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismGetDrivers (_In_ DismSession Session, _In_ BOOL AllDrivers, _Outptr_result_buffer_(*Count) DismDriverPackage** DriverPackage, _Out_ UINT* Count); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismGetDrivers(DismSession Session, [MarshalAs(UnmanagedType.Bool)] bool AllDrivers, out IntPtr DriverPackage, out UInt32 Count); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismGetDrivers(DismSession Session, [MarshalAs(UnmanagedType.Bool)] bool AllDrivers, out IntPtr DriverPackage, out UInt32 Count); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetFeatureInfo.cs b/src/Microsoft.Dism/DismApi.GetFeatureInfo.cs index 391b673..2b9a4f7 100644 --- a/src/Microsoft.Dism/DismApi.GetFeatureInfo.cs +++ b/src/Microsoft.Dism/DismApi.GetFeatureInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -89,8 +89,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismGetFeatureInfo (_In_ DismSession Session, _In_ PCWSTR FeatureName, _In_opt_ PCWSTR Identifier, _In_opt_ DismPackageIdentifier PackageIdentifier, _Out_ DismFeatureInfo** FeatureInfo); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismGetFeatureInfo(DismSession session, string featureName, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr featureInfo); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismGetFeatureInfo(DismSession session, string featureName, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr featureInfo); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetFeatureParent.cs b/src/Microsoft.Dism/DismApi.GetFeatureParent.cs index d9fa667..e6a9e34 100644 --- a/src/Microsoft.Dism/DismApi.GetFeatureParent.cs +++ b/src/Microsoft.Dism/DismApi.GetFeatureParent.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -77,8 +77,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismGetFeatureParent (_In_ DismSession Session, _In_ PCWSTR FeatureName, _In_opt_ PCWSTR Identifier, _In_opt_ DismPackageIdentifier PackageIdentifier, _Outptr_result_buffer_(*Count) DismFeature** Feature, _Out_ UINT* Count); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismGetFeatureParent(DismSession session, string featureName, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr feature, out UInt32 count); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismGetFeatureParent(DismSession session, string featureName, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr feature, out UInt32 count); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetFeatures.cs b/src/Microsoft.Dism/DismApi.GetFeatures.cs index 4e1d9f8..a2e59be 100644 --- a/src/Microsoft.Dism/DismApi.GetFeatures.cs +++ b/src/Microsoft.Dism/DismApi.GetFeatures.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -83,8 +83,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismGetFeatures (_In_ DismSession Session, _In_opt_ PCWSTR Identifier, _In_opt_ DismPackageIdentifier PackageIdentifier, _Outptr_result_buffer_(*Count) DismFeature** Feature, _Out_ UINT* Count); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismGetFeatures(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr feature, out UInt32 count); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismGetFeatures(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr feature, out UInt32 count); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetImageInfo.cs b/src/Microsoft.Dism/DismApi.GetImageInfo.cs index 585c979..d8ce28b 100644 --- a/src/Microsoft.Dism/DismApi.GetImageInfo.cs +++ b/src/Microsoft.Dism/DismApi.GetImageInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -49,8 +49,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismGetImageInfo(_In_ PCWSTR ImageFilePath, _Outptr_result_buffer_(*Count) DismImageInfo** ImageInfo, _Out_ UINT* Count); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismGetImageInfo(string imageFilePath, out IntPtr imageInfo, out UInt32 count); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismGetImageInfo(string imageFilePath, out IntPtr imageInfo, out UInt32 count); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetLastErrorMessage.cs b/src/Microsoft.Dism/DismApi.GetLastErrorMessage.cs index d782b82..0881fb7 100644 --- a/src/Microsoft.Dism/DismApi.GetLastErrorMessage.cs +++ b/src/Microsoft.Dism/DismApi.GetLastErrorMessage.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -62,8 +62,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismGetLastErrorMessage(_Out_ DismString** ErrorMessage); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismGetLastErrorMessage(out IntPtr errorMessage); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismGetLastErrorMessage(out IntPtr errorMessage); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetMountedImages.cs b/src/Microsoft.Dism/DismApi.GetMountedImages.cs index 85cfc60..7e97e41 100644 --- a/src/Microsoft.Dism/DismApi.GetMountedImages.cs +++ b/src/Microsoft.Dism/DismApi.GetMountedImages.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -48,8 +48,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismGetMountedImageInfo(_Outptr_result_buffer_(*Count) DismMountedImageInfo** MountedImageInfo, _Out_ UINT* Count); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismGetMountedImageInfo(out IntPtr mountedImageInfo, out UInt32 count); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismGetMountedImageInfo(out IntPtr mountedImageInfo, out UInt32 count); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetPackageInfo.cs b/src/Microsoft.Dism/DismApi.GetPackageInfo.cs index fb80ea9..65d3eaa 100644 --- a/src/Microsoft.Dism/DismApi.GetPackageInfo.cs +++ b/src/Microsoft.Dism/DismApi.GetPackageInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -73,8 +73,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismGetPackageInfo (_In_ DismSession Session, _In_ PCWSTR Identifier, _In_ DismPackageIdentifier PackageIdentifier, _Out_ DismPackageInfo** PackageInfo); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismGetPackageInfo(DismSession dismSession, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr packageInfo); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismGetPackageInfo(DismSession dismSession, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr packageInfo); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetPackageInfoEx.cs b/src/Microsoft.Dism/DismApi.GetPackageInfoEx.cs index d8bad2c..29c74a5 100644 --- a/src/Microsoft.Dism/DismApi.GetPackageInfoEx.cs +++ b/src/Microsoft.Dism/DismApi.GetPackageInfoEx.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -71,8 +71,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismGetPackageInfoEx (_In_ DismSession Session, _In_ PCWSTR Identifier, _In_ DismPackageIdentifier PackageIdentifier, _Out_ DismPackageInfoEx** PackageInfoEx); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismGetPackageInfoEx(DismSession dismSession, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr packageInfoEx); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismGetPackageInfoEx(DismSession dismSession, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr packageInfoEx); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetPackages.cs b/src/Microsoft.Dism/DismApi.GetPackages.cs index 52ffe72..ca23d32 100644 --- a/src/Microsoft.Dism/DismApi.GetPackages.cs +++ b/src/Microsoft.Dism/DismApi.GetPackages.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -48,8 +48,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismGetPackages (_In_ DismSession Session, _Outptr_result_buffer_(*Count) DismPackage** Package, _Out_ UINT* Count); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismGetPackages(DismSession dismSession, out IntPtr packageInfo, out UInt32 count); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismGetPackages(DismSession dismSession, out IntPtr packageInfo, out UInt32 count); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetProductKeyInfo.cs b/src/Microsoft.Dism/DismApi.GetProductKeyInfo.cs index ebb65d0..ba30e85 100644 --- a/src/Microsoft.Dism/DismApi.GetProductKeyInfo.cs +++ b/src/Microsoft.Dism/DismApi.GetProductKeyInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -46,8 +46,13 @@ internal static partial class NativeMethods /// Pointer that will receive a with the edition ID. /// Pointer that will receive a with the channel name. /// Returns S_OK on success. + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, EntryPoint = "_DismGetProductKeyInfo", StringMarshalling = DismStringMarshalling)] + public static partial int DismGetProductKeyInfo(DismSession session, string productKey, out IntPtr editionIdPtr, out IntPtr channelPtr); + #else [DllImport(DismDllName, EntryPoint = "_DismGetProductKeyInfo", CharSet = DismCharacterSet)] public static extern int DismGetProductKeyInfo(DismSession session, string productKey, out IntPtr editionIdPtr, out IntPtr channelPtr); + #endif } } } diff --git a/src/Microsoft.Dism/DismApi.GetProvisionedAppxPackages.cs b/src/Microsoft.Dism/DismApi.GetProvisionedAppxPackages.cs index 1c626ff..d3a4b4e 100644 --- a/src/Microsoft.Dism/DismApi.GetProvisionedAppxPackages.cs +++ b/src/Microsoft.Dism/DismApi.GetProvisionedAppxPackages.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -41,8 +41,13 @@ internal static partial class NativeMethods /// Receives the array of packages. /// Receives the count of packages. /// Returns S_OK on success. + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int _DismGetProvisionedAppxPackages(DismSession session, out IntPtr packageBufPtr, out UInt32 packageCount); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int _DismGetProvisionedAppxPackages(DismSession session, out IntPtr packageBufPtr, out UInt32 packageCount); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetRegistryMountPoint.cs b/src/Microsoft.Dism/DismApi.GetRegistryMountPoint.cs index 723c150..b6b7d7b 100644 --- a/src/Microsoft.Dism/DismApi.GetRegistryMountPoint.cs +++ b/src/Microsoft.Dism/DismApi.GetRegistryMountPoint.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -44,8 +44,13 @@ internal static partial class NativeMethods /// The to get the mount point for. /// A pointer which will receive the wrapped mount point. /// Returns S_OK on success. + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, EntryPoint = "_DismGetRegistryMountPoint")] + public static partial int DismGetRegistryMountPoint(DismSession session, DismRegistryHive registryHive, out IntPtr registryMountPointPtr); + #else [DllImport(DismDllName, EntryPoint = "_DismGetRegistryMountPoint")] public static extern int DismGetRegistryMountPoint(DismSession session, DismRegistryHive registryHive, out IntPtr registryMountPointPtr); + #endif } } } diff --git a/src/Microsoft.Dism/DismApi.GetTargetEditions.cs b/src/Microsoft.Dism/DismApi.GetTargetEditions.cs index 6e806d3..4111f77 100644 --- a/src/Microsoft.Dism/DismApi.GetTargetEditions.cs +++ b/src/Microsoft.Dism/DismApi.GetTargetEditions.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -40,8 +40,13 @@ internal static partial class NativeMethods /// Pointer to an array of structures containing the target edition IDs of the image. /// The number of edition IDs that are returned. /// Returns S_OK on success. + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, EntryPoint = "_DismGetTargetEditions")] + public static partial int DismGetTargetEditions(DismSession session, out IntPtr editionIds, out uint count); + #else [DllImport(DismDllName, EntryPoint = "_DismGetTargetEditions")] public static extern int DismGetTargetEditions(DismSession session, out IntPtr editionIds, out uint count); + #endif } } } diff --git a/src/Microsoft.Dism/DismApi.Initialize.cs b/src/Microsoft.Dism/DismApi.Initialize.cs index 0253352..942395f 100644 --- a/src/Microsoft.Dism/DismApi.Initialize.cs +++ b/src/Microsoft.Dism/DismApi.Initialize.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -79,8 +79,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismInitialize(_In_ DismLogLevel LogLevel, _In_opt_ PCWSTR LogFilePath, _In_opt_ PCWSTR ScratchDirectory); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismInitialize(DismLogLevel logLevel, string? logFilePath, string? scratchDirectory); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismInitialize(DismLogLevel logLevel, string? logFilePath, string? scratchDirectory); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.MountImage.cs b/src/Microsoft.Dism/DismApi.MountImage.cs index 6b1f7cd..1125a33 100644 --- a/src/Microsoft.Dism/DismApi.MountImage.cs +++ b/src/Microsoft.Dism/DismApi.MountImage.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -273,8 +273,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismMountImage (_In_ PCWSTR ImageFilePath, _In_ PCWSTR MountPath, _In_ UINT ImageIndex, _In_opt_ PCWSTR ImageName, _In_ DismImageIdentifier ImageIdentifier, _In_ DWORD Flags, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismMountImage(string imageFilePath, string mountPath, UInt32 imageIndex, string? imageName, DismImageIdentifier imageIdentifier, UInt32 flags, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismMountImage(string imageFilePath, string mountPath, UInt32 imageIndex, string? imageName, DismImageIdentifier imageIdentifier, UInt32 flags, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.NativeMethods.cs b/src/Microsoft.Dism/DismApi.NativeMethods.cs index cea68ce..f14e232 100644 --- a/src/Microsoft.Dism/DismApi.NativeMethods.cs +++ b/src/Microsoft.Dism/DismApi.NativeMethods.cs @@ -13,8 +13,13 @@ public static partial class DismApi /// internal static partial class NativeMethods { +#if !NET7_0_OR_GREATER private const CharSet DismCharacterSet = CharSet.Unicode; +#endif private const string DismDllName = "DismApi"; +#if NET7_0_OR_GREATER + private const StringMarshalling DismStringMarshalling = StringMarshalling.Utf16; +#endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.OpenSession.cs b/src/Microsoft.Dism/DismApi.OpenSession.cs index 70a47b7..03ea652 100644 --- a/src/Microsoft.Dism/DismApi.OpenSession.cs +++ b/src/Microsoft.Dism/DismApi.OpenSession.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -86,8 +86,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismOpenSession(_In_ PCWSTR ImagePath, _In_opt_ PCWSTR WindowsDirectory, _In_opt_ WCHAR* SystemDrive, _Out_ DismSession* Session); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismOpenSession(string imagePath, string? windowsDirectory, string? systemDrive, out IntPtr session); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismOpenSession(string imagePath, string? windowsDirectory, string? systemDrive, out IntPtr session); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.RemountImage.cs b/src/Microsoft.Dism/DismApi.RemountImage.cs index 61d56c2..6213a13 100644 --- a/src/Microsoft.Dism/DismApi.RemountImage.cs +++ b/src/Microsoft.Dism/DismApi.RemountImage.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -35,8 +35,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismRemountImage(_In_ PCWSTR MountPath); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismRemountImage(string mountPath); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismRemountImage(string mountPath); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.RemoveCapability.cs b/src/Microsoft.Dism/DismApi.RemoveCapability.cs index 9af0161..c5a9112 100644 --- a/src/Microsoft.Dism/DismApi.RemoveCapability.cs +++ b/src/Microsoft.Dism/DismApi.RemoveCapability.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -57,8 +57,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismRemoveCapability(_In_ DismSession Session, _In_ PCWSTR Name, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismRemoveCapability(DismSession session, string name, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismRemoveCapability(DismSession session, string name, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.RemoveDriver.cs b/src/Microsoft.Dism/DismApi.RemoveDriver.cs index 1911879..0086f18 100644 --- a/src/Microsoft.Dism/DismApi.RemoveDriver.cs +++ b/src/Microsoft.Dism/DismApi.RemoveDriver.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -38,8 +38,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismRemoveDriver (_In_ DismSession Session, _In_ PCWSTR DriverPath); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismRemoveDriver(DismSession session, string driverPath); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismRemoveDriver(DismSession session, string driverPath); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.RemovePackage.cs b/src/Microsoft.Dism/DismApi.RemovePackage.cs index f78c8c2..9b1e6e0 100644 --- a/src/Microsoft.Dism/DismApi.RemovePackage.cs +++ b/src/Microsoft.Dism/DismApi.RemovePackage.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -125,8 +125,13 @@ internal static partial class NativeMethods /// The DismRemovePackage function does not support .msu files. /// /// HRESULT WINAPI DismRemovePackage (_In_ DismSession Session, _In_ PCWSTR Identifier, _In_ DismPackageIdentifier PackageIdentifier, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismRemovePackage(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, SafeWaitHandle cancelEvent, DismProgressCallback? progress, IntPtr userData); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismRemovePackage(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, SafeWaitHandle cancelEvent, DismProgressCallback? progress, IntPtr userData); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.RemoveProvisionedAppxPackage.cs b/src/Microsoft.Dism/DismApi.RemoveProvisionedAppxPackage.cs index b3cca58..b6d996a 100644 --- a/src/Microsoft.Dism/DismApi.RemoveProvisionedAppxPackage.cs +++ b/src/Microsoft.Dism/DismApi.RemoveProvisionedAppxPackage.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -29,8 +29,13 @@ internal static partial class NativeMethods /// A valid DISM Session. /// The package name. /// Returns S_OK on success. + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int _DismRemoveProvisionedAppxPackage(DismSession session, [MarshalAs(UnmanagedType.LPWStr)] string packageName); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int _DismRemoveProvisionedAppxPackage(DismSession session, [MarshalAs(UnmanagedType.LPWStr)] string packageName); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs b/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs index 4953b09..b3e43e1 100644 --- a/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs +++ b/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -95,8 +95,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismRestoreImageHealth(_In_ DismSession Session, _In_reads_opt_(SourcePathCount) PCWSTR* SourcePaths, _In_opt_ UINT SourcePathCount, _In_ BOOL LimitAccess, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismRestoreImageHealth(DismSession session, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)] string[] sourcePaths, UInt32 sourcePathCount, [MarshalAs(UnmanagedType.Bool)] bool limitAccess, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismRestoreImageHealth(DismSession session, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)] string[] sourcePaths, UInt32 sourcePathCount, [MarshalAs(UnmanagedType.Bool)] bool limitAccess, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.SetEdition.cs b/src/Microsoft.Dism/DismApi.SetEdition.cs index fc79d89..df29513 100644 --- a/src/Microsoft.Dism/DismApi.SetEdition.cs +++ b/src/Microsoft.Dism/DismApi.SetEdition.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -123,6 +123,16 @@ internal static partial class NativeMethods /// Optional. A pointer to a client-defined DismProgressCallback Function. /// Optional. User defined custom data. /// Returns S_OK on success. + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, EntryPoint = "_DismSetEdition", StringMarshalling = DismStringMarshalling)] + public static partial int DismSetEdition( + DismSession session, + [MarshalAs(UnmanagedType.LPWStr)] string editionID, + [MarshalAs(UnmanagedType.LPWStr)] string? productKey, + SafeWaitHandle cancelEvent, + DismProgressCallback progress, + IntPtr userData); + #else [DllImport(DismDllName, EntryPoint = "_DismSetEdition", CharSet = DismCharacterSet)] public static extern int DismSetEdition( DismSession session, @@ -131,6 +141,7 @@ public static extern int DismSetEdition( SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.SetProductKey.cs b/src/Microsoft.Dism/DismApi.SetProductKey.cs index cb84ebc..235d7fb 100644 --- a/src/Microsoft.Dism/DismApi.SetProductKey.cs +++ b/src/Microsoft.Dism/DismApi.SetProductKey.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -29,8 +29,13 @@ internal static partial class NativeMethods /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. /// The product key. /// Returns S_OK on success. + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, EntryPoint = "_DismSetProductKey", StringMarshalling = DismStringMarshalling)] + public static partial int DismSetProductKey(DismSession session, string productKey); + #else [DllImport(DismDllName, EntryPoint = "_DismSetProductKey", CharSet = DismCharacterSet)] public static extern int DismSetProductKey(DismSession session, string productKey); + #endif } } } diff --git a/src/Microsoft.Dism/DismApi.Shutdown.cs b/src/Microsoft.Dism/DismApi.Shutdown.cs index 7e5497c..dcd09c0 100644 --- a/src/Microsoft.Dism/DismApi.Shutdown.cs +++ b/src/Microsoft.Dism/DismApi.Shutdown.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -49,8 +49,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismShutdown( ); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismShutdown(); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismShutdown(); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.SplitFfuImage.cs b/src/Microsoft.Dism/DismApi.SplitFfuImage.cs index 0be4401..1c8c942 100644 --- a/src/Microsoft.Dism/DismApi.SplitFfuImage.cs +++ b/src/Microsoft.Dism/DismApi.SplitFfuImage.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -28,8 +28,13 @@ internal static partial class NativeMethods /// The path to the SFU file to create. /// The maximum size in megabytes (MB) for each created file. /// Retrusn S_OK on success. + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int _DismSplitFfuImage([MarshalAs(UnmanagedType.LPWStr)] string ImagePath, [MarshalAs(UnmanagedType.LPWStr)] string PartPath, ulong PartSize); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int _DismSplitFfuImage([MarshalAs(UnmanagedType.LPWStr)] string ImagePath, [MarshalAs(UnmanagedType.LPWStr)] string PartPath, ulong PartSize); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.UnmountImage.cs b/src/Microsoft.Dism/DismApi.UnmountImage.cs index 633fde3..1fba9fc 100644 --- a/src/Microsoft.Dism/DismApi.UnmountImage.cs +++ b/src/Microsoft.Dism/DismApi.UnmountImage.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -72,8 +72,13 @@ internal static partial class NativeMethods /// /// HRESULT WINAPI DismUnmountImage(_In_ PCWSTR MountPath, _In_ DWORD Flags, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] + public static partial int DismUnmountImage(string mountPath, UInt32 flags, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #else [DllImport(DismDllName, CharSet = DismCharacterSet)] public static extern int DismUnmountImage(string mountPath, UInt32 flags, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.ValidateProductKey.cs b/src/Microsoft.Dism/DismApi.ValidateProductKey.cs index 9d722e2..700a85c 100644 --- a/src/Microsoft.Dism/DismApi.ValidateProductKey.cs +++ b/src/Microsoft.Dism/DismApi.ValidateProductKey.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -43,8 +43,13 @@ internal static partial class NativeMethods /// if the key is invalid /// /// + #if NET7_0_OR_GREATER + [LibraryImport(DismDllName, EntryPoint = "_DismValidateProductKey", StringMarshalling = DismStringMarshalling)] + public static partial int DismValidateProductKey(DismSession session, string productKey); + #else [DllImport(DismDllName, EntryPoint = "_DismValidateProductKey", CharSet = DismCharacterSet)] public static extern int DismValidateProductKey(DismSession session, string productKey); + #endif } } } diff --git a/src/Microsoft.Dism/DismProgressCallback.cs b/src/Microsoft.Dism/DismProgressCallback.cs index ebb899b..022e11e 100644 --- a/src/Microsoft.Dism/DismProgressCallback.cs +++ b/src/Microsoft.Dism/DismProgressCallback.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. using System; +using System.Runtime.InteropServices; namespace Microsoft.Dism { @@ -24,6 +25,7 @@ public static partial class DismApi /// /// void DismProgressCallback(_In_ UINT Current, _In_ UINT Total, _In_ PVOID UserData) /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] internal delegate void DismProgressCallback(UInt32 current, UInt32 total, IntPtr userData); } } diff --git a/src/Microsoft.Dism/DismUtilities.cs b/src/Microsoft.Dism/DismUtilities.cs index 53ee6b7..6608c5c 100644 --- a/src/Microsoft.Dism/DismUtilities.cs +++ b/src/Microsoft.Dism/DismUtilities.cs @@ -1,4 +1,4 @@ -// Copyright (c). All rights reserved. +// Copyright (c). All rights reserved. // // Licensed under the MIT license. @@ -104,7 +104,7 @@ public enum DismGeneration /// /// Provides utility functions related to DismApi. /// - internal static class DismUtilities + internal static partial class DismUtilities { /// /// The handle of the loaded DISM generational library. @@ -298,7 +298,7 @@ internal static void ThrowIfFail(int hresult, DismSession? session = null, [Call /// /// Native methods necessary for manually loading and unloading Win32 libraries. /// - internal static class NativeMethods + internal static partial class NativeMethods { /// /// Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count. When the reference count reaches zero, the module is unloaded from the address space of the calling process and the handle is no longer valid. @@ -307,8 +307,14 @@ internal static class NativeMethods /// If the function succeeds, the return value is a handle to the module. /// /// If the function fails, the return value is NULL.To get extended error information, call . + #if NET7_0_OR_GREATER + [LibraryImport("kernel32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool FreeLibrary(IntPtr hModule); + #else [DllImport("kernel32.dll")] public static extern bool FreeLibrary(IntPtr hModule); + #endif /// /// Loads the specified module into the address space of the calling process. The specified module may cause other modules to be loaded. @@ -317,8 +323,13 @@ internal static class NativeMethods /// If the function succeeds, the return value is a handle to the module. /// /// If the function fails, the return value is NULL.To get extended error information, call . + #if NET7_0_OR_GREATER + [LibraryImport("kernel32.dll")] + public static partial IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName); + #else [DllImport("kernel32.dll")] public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName); + #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/Microsoft.Dism.csproj b/src/Microsoft.Dism/Microsoft.Dism.csproj index 3e95f1d..3a9de3c 100644 --- a/src/Microsoft.Dism/Microsoft.Dism.csproj +++ b/src/Microsoft.Dism/Microsoft.Dism.csproj @@ -1,14 +1,15 @@  - net40;netstandard2.0;net8.0 + net40;netstandard2.0;net8.0;net10.0 true true - $(ArtifactsBasePath)$(MSBuildProjectName) Managed API for Deployment Image Servicing and Management (DISM) + $(ArtifactsBasePath)$(MSBuildProjectName) Dism README.md $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb true + true From 4fdd7e4a55bf278fcdc9594469bcbebd1cbc39d5 Mon Sep 17 00:00:00 2001 From: Jeff Kluge Date: Fri, 27 Mar 2026 11:31:30 -0700 Subject: [PATCH 02/13] Update version to 5.0 (#284) --- version.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.json b/version.json index a12339d..02a3bda 100644 --- a/version.json +++ b/version.json @@ -1,8 +1,8 @@ { "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "4.0", + "version": "5.0", "assemblyVersion": "1.0", - "versionHeightOffset": -1, + "versionHeightOffset": -2, "publicReleaseRefSpec": [ "^refs/heads/main$", "^refs/tags/v\\d+\\.\\d+\\.\\d+" From a615f14f38d59e897be90b24441c6d9aa0a22c06 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 08:33:11 -0700 Subject: [PATCH 03/13] Bump Microsoft.SourceLink.GitHub from 10.0.103 to 10.0.201 (#286) --- updated-dependencies: - dependency-name: Microsoft.SourceLink.GitHub dependency-version: 10.0.201 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index b3d6152..aa7a684 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -13,7 +13,7 @@ - + From 1c56d65180f3a4995d25ebc6218de37f84ac8392 Mon Sep 17 00:00:00 2001 From: Rolling2405 <89894749+Rolling2405@users.noreply.github.com> Date: Thu, 26 Mar 2026 15:28:59 -0700 Subject: [PATCH 04/13] Modernize for .NET 10: add net10.0 target and convert DllImport to LibraryImport Added net10.0 to TargetFrameworks with AllowUnsafeBlocks for source-generated P/Invoke - Converted all 48 DllImport declarations to LibraryImport with #if NET7_0_OR_GREATER conditional compilation - Added [UnmanagedFunctionPointer] to native callback delegate - Moved ArtifactsPath to Directory.Build.props (NETSDK1199 fix for .NET 10) - All 4 targets build successfully: net40, netstandard2.0, net8.0, net10.0 --- Directory.Build.props | 1 + 1 file changed, 1 insertion(+) diff --git a/Directory.Build.props b/Directory.Build.props index c6f895c..9b16b13 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,7 @@ $(MSBuildThisFileDirectory)artifacts\ + $(ArtifactsBasePath)$(MSBuildProjectName) $(MSBuildThisFileDirectory)key.snk *log true From 5274782fbba33923240f1b6a715a6ed029e6cc85 Mon Sep 17 00:00:00 2001 From: Jeff Kluge Date: Fri, 27 Mar 2026 10:51:08 -0700 Subject: [PATCH 05/13] Feedback --- Directory.Build.props | 1 - 1 file changed, 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 9b16b13..c6f895c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,6 @@ $(MSBuildThisFileDirectory)artifacts\ - $(ArtifactsBasePath)$(MSBuildProjectName) $(MSBuildThisFileDirectory)key.snk *log true From a8e9037a100a0d0ba1fef00e35f95e5a4331184c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 29 Mar 2026 20:54:06 +0000 Subject: [PATCH 06/13] Initial plan From 3b908f2133eeb67c9f1810a4b4e3ee307de531b4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 29 Mar 2026 21:11:34 +0000 Subject: [PATCH 07/13] Fix SA1116 and SA1117 StyleCop violations in async methods - SA1116: Collapse multi-line DismProgress constructor to single line - SA1116: Move first param of Task.Factory.StartNew to its own line - SA1117: Split closing params of Task.Factory.StartNew onto separate lines Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Rolling2405 <89894749+Rolling2405@users.noreply.github.com> --- src/Microsoft.Dism/DismApi.AddCapability.cs | 66 ++++++++++ src/Microsoft.Dism/DismApi.AddPackage.cs | 65 ++++++++++ .../DismApi.CheckImageHealth.cs | 61 ++++++++++ src/Microsoft.Dism/DismApi.CommitImage.cs | 63 ++++++++++ src/Microsoft.Dism/DismApi.DisableFeature.cs | 66 ++++++++++ src/Microsoft.Dism/DismApi.EnableFeature.cs | 115 ++++++++++++++++++ src/Microsoft.Dism/DismApi.MountImage.cs | 92 ++++++++++++++ .../DismApi.RemoveCapability.cs | 62 ++++++++++ src/Microsoft.Dism/DismApi.RemovePackage.cs | 86 +++++++++++++ .../DismApi.RestoreImageHealth.cs | 65 ++++++++++ src/Microsoft.Dism/DismApi.SetEdition.cs | 87 +++++++++++++ src/Microsoft.Dism/DismApi.UnmountImage.cs | 63 ++++++++++ 12 files changed, 891 insertions(+) diff --git a/src/Microsoft.Dism/DismApi.AddCapability.cs b/src/Microsoft.Dism/DismApi.AddCapability.cs index 309688a..7e1b924 100644 --- a/src/Microsoft.Dism/DismApi.AddCapability.cs +++ b/src/Microsoft.Dism/DismApi.AddCapability.cs @@ -6,6 +6,8 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.Dism { @@ -63,6 +65,70 @@ public static void AddCapability(DismSession session, string capabilityName, boo DismUtilities.ThrowIfFail(hresult, session); } +#if !NET40 + /// + /// Asynchronously adds a capability to an image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. + /// The name of the capability that is being added. + /// The flag indicates whether WU/WSUS should be contacted as a source location for downloading the payload of a capability. If payload of the capability to be added exists, the flag is ignored. + /// A list of source locations. The function shall look up removed payload files from the locations specified in SourcePaths, and if not found, continue the search by contacting WU/WSUS depending on parameter LimitAccess. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task AddCapabilityAsync(DismSession session, string capabilityName, bool limitAccess, List? sourcePaths, IProgress? progress = null, CancellationToken cancellationToken = default) + { + var tcs = new TaskCompletionSource(); + + var ctsRegistration = default(CancellationTokenRegistration); + + Task.Factory.StartNew( + () => + { + try + { + string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; + + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + + int hresult = NativeMethods.DismAddCapability(session, capabilityName, limitAccess, sourcePathsArray, (uint)sourcePathsArray.Length, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) + { + tcs.TrySetCanceled(cancellationToken); + } + catch (Exception ex) + { + tcs.TrySetException(ex); + } + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return tcs.Task; + } +#endif + internal static partial class NativeMethods { /// diff --git a/src/Microsoft.Dism/DismApi.AddPackage.cs b/src/Microsoft.Dism/DismApi.AddPackage.cs index b492905..fa40571 100644 --- a/src/Microsoft.Dism/DismApi.AddPackage.cs +++ b/src/Microsoft.Dism/DismApi.AddPackage.cs @@ -5,6 +5,8 @@ using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.Dism { @@ -65,6 +67,69 @@ public static void AddPackage(DismSession session, string packagePath, bool igno DismUtilities.ThrowIfFail(hresult, session); } +#if !NET40 + /// + /// Asynchronously adds a single .cab or .msu file to a Windows® image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the OpenSession method. + /// A relative or absolute path to the .cab or .msu file being added or a folder containing the expanded files of a single .cab file. + /// Specifies whether to ignore the internal applicability checks that are done when a package is added. + /// Specifies whether to add a package if it has pending online actions. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + /// When the package is not applicable to the specified session. + public static Task AddPackageAsync(DismSession session, string packagePath, bool ignoreCheck, bool preventPending, IProgress? progress = null, CancellationToken cancellationToken = default) + { + var tcs = new TaskCompletionSource(); + + var ctsRegistration = default(CancellationTokenRegistration); + + Task.Factory.StartNew( + () => + { + try + { + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + + int hresult = NativeMethods.DismAddPackage(session, packagePath, ignoreCheck, preventPending, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) + { + tcs.TrySetCanceled(cancellationToken); + } + catch (Exception ex) + { + tcs.TrySetException(ex); + } + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return tcs.Task; + } +#endif + internal static partial class NativeMethods { /// diff --git a/src/Microsoft.Dism/DismApi.CheckImageHealth.cs b/src/Microsoft.Dism/DismApi.CheckImageHealth.cs index bbb2cfe..2187b0b 100644 --- a/src/Microsoft.Dism/DismApi.CheckImageHealth.cs +++ b/src/Microsoft.Dism/DismApi.CheckImageHealth.cs @@ -5,6 +5,8 @@ using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.Dism { @@ -58,6 +60,65 @@ public static DismImageHealthState CheckImageHealth(DismSession session, bool sc return imageHealthState; } +#if !NET40 + /// + /// Asynchronously checks whether the image can be serviced or whether it is corrupted. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// Specifies whether to scan the image or just check for flags from a previous scan. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation, containing the health state of the image. + /// When a failure occurs. + /// When the operation is canceled. + public static Task CheckImageHealthAsync(DismSession session, bool scanImage, IProgress? progress = null, CancellationToken cancellationToken = default) + { + var tcs = new TaskCompletionSource(); + + var ctsRegistration = default(CancellationTokenRegistration); + + Task.Factory.StartNew( + () => + { + try + { + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + + int hresult = NativeMethods.DismCheckImageHealth(session, scanImage, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero, out DismImageHealthState imageHealthState); + + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(imageHealthState); + } + } + catch (OperationCanceledException) + { + tcs.TrySetCanceled(cancellationToken); + } + catch (Exception ex) + { + tcs.TrySetException(ex); + } + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return tcs.Task; + } +#endif + internal static partial class NativeMethods { /// diff --git a/src/Microsoft.Dism/DismApi.CommitImage.cs b/src/Microsoft.Dism/DismApi.CommitImage.cs index e260d76..b42f5db 100644 --- a/src/Microsoft.Dism/DismApi.CommitImage.cs +++ b/src/Microsoft.Dism/DismApi.CommitImage.cs @@ -5,6 +5,8 @@ using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.Dism { @@ -56,6 +58,67 @@ public static void CommitImage(DismSession session, bool discardChanges, Microso DismUtilities.ThrowIfFail(hresult, session); } +#if !NET40 + /// + /// Asynchronously commits the changes made to a Windows® image in a mounted .wim or .vhd file. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. + /// true or false to discard changes made to the image. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + public static Task CommitImageAsync(DismSession session, bool discardChanges, IProgress? progress = null, CancellationToken cancellationToken = default) + { + var tcs = new TaskCompletionSource(); + + var ctsRegistration = default(CancellationTokenRegistration); + + Task.Factory.StartNew( + () => + { + try + { + UInt32 flags = discardChanges ? DISM_DISCARD_IMAGE : DISM_COMMIT_IMAGE; + + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + + int hresult = NativeMethods.DismCommitImage(session, flags, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) + { + tcs.TrySetCanceled(cancellationToken); + } + catch (Exception ex) + { + tcs.TrySetException(ex); + } + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return tcs.Task; + } +#endif + internal static partial class NativeMethods { /// diff --git a/src/Microsoft.Dism/DismApi.DisableFeature.cs b/src/Microsoft.Dism/DismApi.DisableFeature.cs index 5ec65f1..3f50506 100644 --- a/src/Microsoft.Dism/DismApi.DisableFeature.cs +++ b/src/Microsoft.Dism/DismApi.DisableFeature.cs @@ -5,6 +5,8 @@ using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.Dism { @@ -68,6 +70,70 @@ public static void DisableFeature(DismSession session, string featureName, strin DismUtilities.ThrowIfFail(hresult, session); } +#if !NET40 + /// + /// Asynchronously disables a feature in the current image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that you want to disable. To disable more than one feature, separate each feature name with a semicolon. + /// Optional. The name of the parent package that the feature is a part of. + /// + /// This is an optional parameter. If no package is specified, then the default Windows® Foundation package is used. + /// Specifies whether to remove the files required to enable the feature. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task DisableFeatureAsync(DismSession session, string featureName, string packageName, bool removePayload, IProgress? progress = null, CancellationToken cancellationToken = default) + { + var tcs = new TaskCompletionSource(); + + var ctsRegistration = default(CancellationTokenRegistration); + + Task.Factory.StartNew( + () => + { + try + { + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + + int hresult = NativeMethods.DismDisableFeature(session, featureName, packageName, removePayload, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) + { + tcs.TrySetCanceled(cancellationToken); + } + catch (Exception ex) + { + tcs.TrySetException(ex); + } + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return tcs.Task; + } +#endif + internal static partial class NativeMethods { /// diff --git a/src/Microsoft.Dism/DismApi.EnableFeature.cs b/src/Microsoft.Dism/DismApi.EnableFeature.cs index 9288457..270a5ee 100644 --- a/src/Microsoft.Dism/DismApi.EnableFeature.cs +++ b/src/Microsoft.Dism/DismApi.EnableFeature.cs @@ -6,6 +6,8 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.Dism { @@ -242,6 +244,119 @@ private static void EnableFeature(DismSession session, string featureName, strin DismUtilities.ThrowIfFail(hresult, session); } +#if !NET40 + /// + /// Asynchronously enables a feature from the default package. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. + /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. + /// A list of source locations to check for files needed to enable the feature. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task EnableFeatureAsync(DismSession session, string featureName, bool limitAccess, bool enableAll, List? sourcePaths = null, IProgress? progress = null, CancellationToken cancellationToken = default) + { + return EnableFeatureAsync(session, featureName, null, DismPackageIdentifier.None, limitAccess, enableAll, sourcePaths, progress, cancellationToken); + } + + /// + /// Asynchronously enables a feature from the specified package name. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// The name of the package that contains the feature. + /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. + /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. + /// A list of source locations to check for files needed to enable the feature. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task EnableFeatureByPackageNameAsync(DismSession session, string featureName, string packageName, bool limitAccess, bool enableAll, List? sourcePaths = null, IProgress? progress = null, CancellationToken cancellationToken = default) + { + return EnableFeatureAsync(session, featureName, packageName, DismPackageIdentifier.Name, limitAccess, enableAll, sourcePaths, progress, cancellationToken); + } + + /// + /// Asynchronously enables a feature from the specified package path. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// The path of the package that contains the feature. + /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. + /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. + /// A list of source locations to check for files needed to enable the feature. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task EnableFeatureByPackagePathAsync(DismSession session, string featureName, string packagePath, bool limitAccess, bool enableAll, List? sourcePaths = null, IProgress? progress = null, CancellationToken cancellationToken = default) + { + return EnableFeatureAsync(session, featureName, packagePath, DismPackageIdentifier.Path, limitAccess, enableAll, sourcePaths, progress, cancellationToken); + } + + /// + /// Asynchronously enables a feature in an image. + /// + private static Task EnableFeatureAsync(DismSession session, string featureName, string? identifier, DismPackageIdentifier packageIdentifier, bool limitAccess, bool enableAll, List? sourcePaths, IProgress? progress, CancellationToken cancellationToken) + { + var tcs = new TaskCompletionSource(); + + var ctsRegistration = default(CancellationTokenRegistration); + + Task.Factory.StartNew( + () => + { + try + { + string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; + + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + + int hresult = NativeMethods.DismEnableFeature(session, featureName, identifier, identifier == null ? DismPackageIdentifier.None : packageIdentifier, limitAccess, sourcePathsArray, (uint)sourcePathsArray.Length, enableAll, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) + { + tcs.TrySetCanceled(cancellationToken); + } + catch (Exception ex) + { + tcs.TrySetException(ex); + } + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return tcs.Task; + } +#endif + internal static partial class NativeMethods { /// diff --git a/src/Microsoft.Dism/DismApi.MountImage.cs b/src/Microsoft.Dism/DismApi.MountImage.cs index 1125a33..dc73b81 100644 --- a/src/Microsoft.Dism/DismApi.MountImage.cs +++ b/src/Microsoft.Dism/DismApi.MountImage.cs @@ -5,6 +5,8 @@ using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.Dism { @@ -241,6 +243,96 @@ private static void MountImage(string imageFilePath, string mountPath, int image DismUtilities.ThrowIfFail(hresult); } +#if !NET40 + /// + /// Asynchronously mounts a WIM or VHD image file to a specified location using an image index. + /// + /// The path to the WIM or VHD file on the local computer. A .wim, .vhd, or .vhdx file name extension is required. + /// The path of the location where the image should be mounted. This mount path must already exist on the computer. The Windows image in a .wim, .vhd, or .vhdx file can be mounted to an empty folder on an NTFS formatted drive. A Windows image in a .vhd or .vhdx file can also be mounted to an unassigned drive letter. You cannot mount an image to the root of the existing drive. + /// The index of the image in the WIM file that you want to mount. For a VHD file, you must specify an index of 1. + /// Specifies if the image should be mounted in read-only mode. + /// Specifies options to use when mounting an image. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + public static Task MountImageAsync(string imageFilePath, string mountPath, int imageIndex, bool readOnly, DismMountImageOptions options = DismMountImageOptions.None, IProgress? progress = null, CancellationToken cancellationToken = default) + { + return MountImageAsync(imageFilePath, mountPath, imageIndex, null, DismImageIdentifier.ImageIndex, readOnly, options, progress, cancellationToken); + } + + /// + /// Asynchronously mounts a WIM or VHD image file to a specified location using an image name. + /// + /// The path to the WIM or VHD file on the local computer. A .wim, .vhd, or .vhdx file name extension is required. + /// The path of the location where the image should be mounted. This mount path must already exist on the computer. The Windows image in a .wim, .vhd, or .vhdx file can be mounted to an empty folder on an NTFS formatted drive. A Windows image in a .vhd or .vhdx file can also be mounted to an unassigned drive letter. You cannot mount an image to the root of the existing drive. + /// The name of the image that you want to mount. + /// Specifies if the image should be mounted in read-only mode. + /// Specifies options to use when mounting an image. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + public static Task MountImageAsync(string imageFilePath, string mountPath, string? imageName, bool readOnly, DismMountImageOptions options = DismMountImageOptions.None, IProgress? progress = null, CancellationToken cancellationToken = default) + { + return MountImageAsync(imageFilePath, mountPath, 0, imageName, DismImageIdentifier.ImageName, readOnly, options, progress, cancellationToken); + } + + /// + /// Asynchronously mounts a WIM or VHD image file to a specified location. + /// + private static Task MountImageAsync(string imageFilePath, string mountPath, int imageIndex, string? imageName, DismImageIdentifier imageIdentifier, bool readOnly, DismMountImageOptions options, IProgress? progress, CancellationToken cancellationToken) + { + var tcs = new TaskCompletionSource(); + + var ctsRegistration = default(CancellationTokenRegistration); + + Task.Factory.StartNew( + () => + { + try + { + uint flags = (readOnly ? DISM_MOUNT_READONLY : DISM_MOUNT_READWRITE) | (uint)options; + + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + + int hresult = NativeMethods.DismMountImage(imageFilePath, mountPath, (uint)imageIndex, imageName, imageIdentifier, flags, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) + { + tcs.TrySetCanceled(cancellationToken); + } + catch (Exception ex) + { + tcs.TrySetException(ex); + } + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return tcs.Task; + } +#endif + internal static partial class NativeMethods { /// diff --git a/src/Microsoft.Dism/DismApi.RemoveCapability.cs b/src/Microsoft.Dism/DismApi.RemoveCapability.cs index c5a9112..c1832cf 100644 --- a/src/Microsoft.Dism/DismApi.RemoveCapability.cs +++ b/src/Microsoft.Dism/DismApi.RemoveCapability.cs @@ -5,6 +5,8 @@ using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.Dism { @@ -42,6 +44,66 @@ public static void RemoveCapability(DismSession session, string capabilityName, DismUtilities.ThrowIfFail(hresult, session); } +#if !NET40 + /// + /// Asynchronously removes the capability from an image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the capability that is being removed. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task RemoveCapabilityAsync(DismSession session, string capabilityName, IProgress? progress = null, CancellationToken cancellationToken = default) + { + var tcs = new TaskCompletionSource(); + + var ctsRegistration = default(CancellationTokenRegistration); + + Task.Factory.StartNew( + () => + { + try + { + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + + int hresult = NativeMethods.DismRemoveCapability(session, capabilityName, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) + { + tcs.TrySetCanceled(cancellationToken); + } + catch (Exception ex) + { + tcs.TrySetException(ex); + } + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return tcs.Task; + } +#endif + internal static partial class NativeMethods { /// diff --git a/src/Microsoft.Dism/DismApi.RemovePackage.cs b/src/Microsoft.Dism/DismApi.RemovePackage.cs index 9b1e6e0..739234e 100644 --- a/src/Microsoft.Dism/DismApi.RemovePackage.cs +++ b/src/Microsoft.Dism/DismApi.RemovePackage.cs @@ -5,6 +5,8 @@ using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.Dism { @@ -110,6 +112,90 @@ private static void RemovePackage(DismSession session, string identifier, DismPa DismUtilities.ThrowIfFail(hresult, session); } +#if !NET40 + /// + /// Asynchronously removes a package from an image by name. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The package name. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task RemovePackageByNameAsync(DismSession session, string packageName, IProgress? progress = null, CancellationToken cancellationToken = default) + { + return RemovePackageAsync(session, packageName, DismPackageIdentifier.Name, progress, cancellationToken); + } + + /// + /// Asynchronously removes a package from an image by path. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The package path. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task RemovePackageByPathAsync(DismSession session, string packagePath, IProgress? progress = null, CancellationToken cancellationToken = default) + { + return RemovePackageAsync(session, packagePath, DismPackageIdentifier.Path, progress, cancellationToken); + } + + /// + /// Asynchronously removes a package from an image. + /// + private static Task RemovePackageAsync(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, IProgress? progress, CancellationToken cancellationToken) + { + var tcs = new TaskCompletionSource(); + + var ctsRegistration = default(CancellationTokenRegistration); + + Task.Factory.StartNew( + () => + { + try + { + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + + int hresult = NativeMethods.DismRemovePackage(session, identifier, packageIdentifier, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) + { + tcs.TrySetCanceled(cancellationToken); + } + catch (Exception ex) + { + tcs.TrySetException(ex); + } + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return tcs.Task; + } +#endif + internal static partial class NativeMethods { /// diff --git a/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs b/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs index b3e43e1..5d60adf 100644 --- a/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs +++ b/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs @@ -6,6 +6,8 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.Dism { @@ -75,6 +77,69 @@ public static void RestoreImageHealth(DismSession session, bool limitAccess, Lis DismUtilities.ThrowIfFail(hresult, session); } +#if !NET40 + /// + /// Asynchronously repairs a corrupted image that has been identified as repairable by the CheckImageHealth Function. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// Specifies whether the RestoreImageHealth method should contact Windows Update (WU) as a source location for downloading repair files. Before checking WU, DISM will check for the files in the sourcePaths provided and in any locations specified in the registry by Group Policy. If the files that are required to enable the feature are found in these other specified locations, this flag is ignored. + /// List of source locations to check for repair files. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task RestoreImageHealthAsync(DismSession session, bool limitAccess, List? sourcePaths = null, IProgress? progress = null, CancellationToken cancellationToken = default) + { + var tcs = new TaskCompletionSource(); + + var ctsRegistration = default(CancellationTokenRegistration); + + Task.Factory.StartNew( + () => + { + try + { + string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; + + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + + int hresult = NativeMethods.DismRestoreImageHealth(session, sourcePathsArray, (uint)sourcePathsArray.Length, limitAccess, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) + { + tcs.TrySetCanceled(cancellationToken); + } + catch (Exception ex) + { + tcs.TrySetException(ex); + } + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return tcs.Task; + } +#endif + internal static partial class NativeMethods { /// diff --git a/src/Microsoft.Dism/DismApi.SetEdition.cs b/src/Microsoft.Dism/DismApi.SetEdition.cs index df29513..1d42f57 100644 --- a/src/Microsoft.Dism/DismApi.SetEdition.cs +++ b/src/Microsoft.Dism/DismApi.SetEdition.cs @@ -5,6 +5,8 @@ using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.Dism { @@ -111,6 +113,91 @@ private static void SetEdition(DismSession session, string editionId, string? pr DismUtilities.ThrowIfFail(hresult, session); } +#if !NET40 + /// + /// Asynchronously changes an offline Windows image to a higher edition. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. + /// The edition to set the image to. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task SetEditionAsync(DismSession session, string editionId, IProgress? progress = null, CancellationToken cancellationToken = default) + { + return SetEditionAsync(session, editionId, productKey: null, progress, cancellationToken); + } + + /// + /// Asynchronously changes an offline Windows image to a higher edition and sets the product key. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. + /// The edition to set the image to. + /// A product key for the specified edition. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task SetEditionAndProductKeyAsync(DismSession session, string editionId, string productKey, IProgress? progress = null, CancellationToken cancellationToken = default) + { + return SetEditionAsync(session, editionId, productKey, progress, cancellationToken); + } + + /// + /// Asynchronously changes an offline Windows image to a higher edition and optionally sets the product key. + /// + private static Task SetEditionAsync(DismSession session, string editionId, string? productKey, IProgress? progress, CancellationToken cancellationToken) + { + var tcs = new TaskCompletionSource(); + + var ctsRegistration = default(CancellationTokenRegistration); + + Task.Factory.StartNew( + () => + { + try + { + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + + int hresult = NativeMethods.DismSetEdition(session, editionId, productKey, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) + { + tcs.TrySetCanceled(cancellationToken); + } + catch (Exception ex) + { + tcs.TrySetException(ex); + } + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return tcs.Task; + } +#endif + internal static partial class NativeMethods { /// diff --git a/src/Microsoft.Dism/DismApi.UnmountImage.cs b/src/Microsoft.Dism/DismApi.UnmountImage.cs index 1fba9fc..73b7af9 100644 --- a/src/Microsoft.Dism/DismApi.UnmountImage.cs +++ b/src/Microsoft.Dism/DismApi.UnmountImage.cs @@ -5,6 +5,8 @@ using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.Dism { @@ -56,6 +58,67 @@ public static void UnmountImage(string mountPath, bool commitChanges, Dism.DismP DismUtilities.ThrowIfFail(hresult); } +#if !NET40 + /// + /// Asynchronously unmounts a Windows image from a specified location. + /// + /// A relative or absolute path to the mount directory of the image. + /// Specifies whether or not the changes to the image should be saved. + /// An optional progress provider to receive progress updates. + /// A cancellation token to cancel the operation. + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + public static Task UnmountImageAsync(string mountPath, bool commitChanges, IProgress? progress = null, CancellationToken cancellationToken = default) + { + var tcs = new TaskCompletionSource(); + + var ctsRegistration = default(CancellationTokenRegistration); + + Task.Factory.StartNew( + () => + { + try + { + uint flags = commitChanges ? DISM_COMMIT_IMAGE : DISM_DISCARD_IMAGE; + + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + + int hresult = NativeMethods.DismUnmountImage(mountPath, flags, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) + { + tcs.TrySetCanceled(cancellationToken); + } + catch (Exception ex) + { + tcs.TrySetException(ex); + } + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return tcs.Task; + } +#endif + internal static partial class NativeMethods { /// From 877a8aa4c39bc9a9cb6ab6da70a17cffd6524f6f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 29 Mar 2026 21:16:35 +0000 Subject: [PATCH 08/13] Fix SA1137/SA1117 StyleCop indentation in async Task.Factory.StartNew blocks Reindent lambda body and trailing parameters in all 12 async method files so that the opening brace, body, and remaining arguments are consistently indented at 16 spaces (one level deeper than the method call), satisfying SA1137 (same indentation) and SA1117 (each parameter on its own line). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Rolling2405 <89894749+Rolling2405@users.noreply.github.com> --- src/Microsoft.Dism/DismApi.AddCapability.cs | 54 +++++++++---------- src/Microsoft.Dism/DismApi.AddPackage.cs | 52 +++++++++--------- .../DismApi.CheckImageHealth.cs | 52 +++++++++--------- src/Microsoft.Dism/DismApi.CommitImage.cs | 54 +++++++++---------- src/Microsoft.Dism/DismApi.DisableFeature.cs | 52 +++++++++--------- src/Microsoft.Dism/DismApi.EnableFeature.cs | 54 +++++++++---------- src/Microsoft.Dism/DismApi.MountImage.cs | 54 +++++++++---------- .../DismApi.RemoveCapability.cs | 52 +++++++++--------- src/Microsoft.Dism/DismApi.RemovePackage.cs | 52 +++++++++--------- .../DismApi.RestoreImageHealth.cs | 54 +++++++++---------- src/Microsoft.Dism/DismApi.SetEdition.cs | 52 +++++++++--------- src/Microsoft.Dism/DismApi.UnmountImage.cs | 54 +++++++++---------- 12 files changed, 318 insertions(+), 318 deletions(-) diff --git a/src/Microsoft.Dism/DismApi.AddCapability.cs b/src/Microsoft.Dism/DismApi.AddCapability.cs index 7e1b924..da26570 100644 --- a/src/Microsoft.Dism/DismApi.AddCapability.cs +++ b/src/Microsoft.Dism/DismApi.AddCapability.cs @@ -87,43 +87,43 @@ public static Task AddCapabilityAsync(DismSession session, string capabilityName Task.Factory.StartNew( () => - { - try { - string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; + try + { + string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - int hresult = NativeMethods.DismAddCapability(session, capabilityName, limitAccess, sourcePathsArray, (uint)sourcePathsArray.Length, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + int hresult = NativeMethods.DismAddCapability(session, capabilityName, limitAccess, sourcePathsArray, (uint)sourcePathsArray.Length, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - if (cancellationToken.IsCancellationRequested) + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) { tcs.TrySetCanceled(cancellationToken); } - else + catch (Exception ex) { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); + tcs.TrySetException(ex); } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - cancellationToken, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); return tcs.Task; } diff --git a/src/Microsoft.Dism/DismApi.AddPackage.cs b/src/Microsoft.Dism/DismApi.AddPackage.cs index fa40571..38fae3f 100644 --- a/src/Microsoft.Dism/DismApi.AddPackage.cs +++ b/src/Microsoft.Dism/DismApi.AddPackage.cs @@ -90,41 +90,41 @@ public static Task AddPackageAsync(DismSession session, string packagePath, bool Task.Factory.StartNew( () => - { - try { - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + try + { + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - int hresult = NativeMethods.DismAddPackage(session, packagePath, ignoreCheck, preventPending, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + int hresult = NativeMethods.DismAddPackage(session, packagePath, ignoreCheck, preventPending, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - if (cancellationToken.IsCancellationRequested) + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) { tcs.TrySetCanceled(cancellationToken); } - else + catch (Exception ex) { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); + tcs.TrySetException(ex); } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - cancellationToken, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); return tcs.Task; } diff --git a/src/Microsoft.Dism/DismApi.CheckImageHealth.cs b/src/Microsoft.Dism/DismApi.CheckImageHealth.cs index 2187b0b..84b667a 100644 --- a/src/Microsoft.Dism/DismApi.CheckImageHealth.cs +++ b/src/Microsoft.Dism/DismApi.CheckImageHealth.cs @@ -79,41 +79,41 @@ public static Task CheckImageHealthAsync(DismSession sessi Task.Factory.StartNew( () => - { - try { - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + try + { + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - int hresult = NativeMethods.DismCheckImageHealth(session, scanImage, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero, out DismImageHealthState imageHealthState); + int hresult = NativeMethods.DismCheckImageHealth(session, scanImage, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero, out DismImageHealthState imageHealthState); - if (cancellationToken.IsCancellationRequested) + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(imageHealthState); + } + } + catch (OperationCanceledException) { tcs.TrySetCanceled(cancellationToken); } - else + catch (Exception ex) { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(imageHealthState); + tcs.TrySetException(ex); } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - cancellationToken, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); return tcs.Task; } diff --git a/src/Microsoft.Dism/DismApi.CommitImage.cs b/src/Microsoft.Dism/DismApi.CommitImage.cs index b42f5db..cd0aa76 100644 --- a/src/Microsoft.Dism/DismApi.CommitImage.cs +++ b/src/Microsoft.Dism/DismApi.CommitImage.cs @@ -77,43 +77,43 @@ public static Task CommitImageAsync(DismSession session, bool discardChanges, IP Task.Factory.StartNew( () => - { - try { - UInt32 flags = discardChanges ? DISM_DISCARD_IMAGE : DISM_COMMIT_IMAGE; + try + { + UInt32 flags = discardChanges ? DISM_DISCARD_IMAGE : DISM_COMMIT_IMAGE; - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - int hresult = NativeMethods.DismCommitImage(session, flags, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + int hresult = NativeMethods.DismCommitImage(session, flags, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - if (cancellationToken.IsCancellationRequested) + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) { tcs.TrySetCanceled(cancellationToken); } - else + catch (Exception ex) { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); + tcs.TrySetException(ex); } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - cancellationToken, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); return tcs.Task; } diff --git a/src/Microsoft.Dism/DismApi.DisableFeature.cs b/src/Microsoft.Dism/DismApi.DisableFeature.cs index 3f50506..9be4485 100644 --- a/src/Microsoft.Dism/DismApi.DisableFeature.cs +++ b/src/Microsoft.Dism/DismApi.DisableFeature.cs @@ -94,41 +94,41 @@ public static Task DisableFeatureAsync(DismSession session, string featureName, Task.Factory.StartNew( () => - { - try { - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + try + { + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - int hresult = NativeMethods.DismDisableFeature(session, featureName, packageName, removePayload, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + int hresult = NativeMethods.DismDisableFeature(session, featureName, packageName, removePayload, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - if (cancellationToken.IsCancellationRequested) + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) { tcs.TrySetCanceled(cancellationToken); } - else + catch (Exception ex) { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); + tcs.TrySetException(ex); } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - cancellationToken, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); return tcs.Task; } diff --git a/src/Microsoft.Dism/DismApi.EnableFeature.cs b/src/Microsoft.Dism/DismApi.EnableFeature.cs index 270a5ee..2a1b154 100644 --- a/src/Microsoft.Dism/DismApi.EnableFeature.cs +++ b/src/Microsoft.Dism/DismApi.EnableFeature.cs @@ -315,43 +315,43 @@ private static Task EnableFeatureAsync(DismSession session, string featureName, Task.Factory.StartNew( () => - { - try { - string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; + try + { + string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - int hresult = NativeMethods.DismEnableFeature(session, featureName, identifier, identifier == null ? DismPackageIdentifier.None : packageIdentifier, limitAccess, sourcePathsArray, (uint)sourcePathsArray.Length, enableAll, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + int hresult = NativeMethods.DismEnableFeature(session, featureName, identifier, identifier == null ? DismPackageIdentifier.None : packageIdentifier, limitAccess, sourcePathsArray, (uint)sourcePathsArray.Length, enableAll, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - if (cancellationToken.IsCancellationRequested) + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) { tcs.TrySetCanceled(cancellationToken); } - else + catch (Exception ex) { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); + tcs.TrySetException(ex); } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - cancellationToken, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); return tcs.Task; } diff --git a/src/Microsoft.Dism/DismApi.MountImage.cs b/src/Microsoft.Dism/DismApi.MountImage.cs index dc73b81..7d267e5 100644 --- a/src/Microsoft.Dism/DismApi.MountImage.cs +++ b/src/Microsoft.Dism/DismApi.MountImage.cs @@ -291,43 +291,43 @@ private static Task MountImageAsync(string imageFilePath, string mountPath, int Task.Factory.StartNew( () => - { - try { - uint flags = (readOnly ? DISM_MOUNT_READONLY : DISM_MOUNT_READWRITE) | (uint)options; + try + { + uint flags = (readOnly ? DISM_MOUNT_READONLY : DISM_MOUNT_READWRITE) | (uint)options; - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - int hresult = NativeMethods.DismMountImage(imageFilePath, mountPath, (uint)imageIndex, imageName, imageIdentifier, flags, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + int hresult = NativeMethods.DismMountImage(imageFilePath, mountPath, (uint)imageIndex, imageName, imageIdentifier, flags, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - if (cancellationToken.IsCancellationRequested) + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) { tcs.TrySetCanceled(cancellationToken); } - else + catch (Exception ex) { - DismUtilities.ThrowIfFail(hresult); - tcs.TrySetResult(true); + tcs.TrySetException(ex); } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - cancellationToken, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); return tcs.Task; } diff --git a/src/Microsoft.Dism/DismApi.RemoveCapability.cs b/src/Microsoft.Dism/DismApi.RemoveCapability.cs index c1832cf..e296a04 100644 --- a/src/Microsoft.Dism/DismApi.RemoveCapability.cs +++ b/src/Microsoft.Dism/DismApi.RemoveCapability.cs @@ -64,41 +64,41 @@ public static Task RemoveCapabilityAsync(DismSession session, string capabilityN Task.Factory.StartNew( () => - { - try { - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + try + { + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - int hresult = NativeMethods.DismRemoveCapability(session, capabilityName, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + int hresult = NativeMethods.DismRemoveCapability(session, capabilityName, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - if (cancellationToken.IsCancellationRequested) + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) { tcs.TrySetCanceled(cancellationToken); } - else + catch (Exception ex) { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); + tcs.TrySetException(ex); } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - cancellationToken, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); return tcs.Task; } diff --git a/src/Microsoft.Dism/DismApi.RemovePackage.cs b/src/Microsoft.Dism/DismApi.RemovePackage.cs index 739234e..e712507 100644 --- a/src/Microsoft.Dism/DismApi.RemovePackage.cs +++ b/src/Microsoft.Dism/DismApi.RemovePackage.cs @@ -156,41 +156,41 @@ private static Task RemovePackageAsync(DismSession session, string identifier, D Task.Factory.StartNew( () => - { - try { - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + try + { + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - int hresult = NativeMethods.DismRemovePackage(session, identifier, packageIdentifier, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + int hresult = NativeMethods.DismRemovePackage(session, identifier, packageIdentifier, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - if (cancellationToken.IsCancellationRequested) + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) { tcs.TrySetCanceled(cancellationToken); } - else + catch (Exception ex) { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); + tcs.TrySetException(ex); } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - cancellationToken, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); return tcs.Task; } diff --git a/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs b/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs index 5d60adf..ec515de 100644 --- a/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs +++ b/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs @@ -98,43 +98,43 @@ public static Task RestoreImageHealthAsync(DismSession session, bool limitAccess Task.Factory.StartNew( () => - { - try { - string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; + try + { + string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - int hresult = NativeMethods.DismRestoreImageHealth(session, sourcePathsArray, (uint)sourcePathsArray.Length, limitAccess, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + int hresult = NativeMethods.DismRestoreImageHealth(session, sourcePathsArray, (uint)sourcePathsArray.Length, limitAccess, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - if (cancellationToken.IsCancellationRequested) + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) { tcs.TrySetCanceled(cancellationToken); } - else + catch (Exception ex) { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); + tcs.TrySetException(ex); } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - cancellationToken, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); return tcs.Task; } diff --git a/src/Microsoft.Dism/DismApi.SetEdition.cs b/src/Microsoft.Dism/DismApi.SetEdition.cs index 1d42f57..0003f40 100644 --- a/src/Microsoft.Dism/DismApi.SetEdition.cs +++ b/src/Microsoft.Dism/DismApi.SetEdition.cs @@ -158,41 +158,41 @@ private static Task SetEditionAsync(DismSession session, string editionId, strin Task.Factory.StartNew( () => - { - try { - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + try + { + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - int hresult = NativeMethods.DismSetEdition(session, editionId, productKey, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + int hresult = NativeMethods.DismSetEdition(session, editionId, productKey, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - if (cancellationToken.IsCancellationRequested) + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult, session); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) { tcs.TrySetCanceled(cancellationToken); } - else + catch (Exception ex) { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); + tcs.TrySetException(ex); } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - cancellationToken, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); return tcs.Task; } diff --git a/src/Microsoft.Dism/DismApi.UnmountImage.cs b/src/Microsoft.Dism/DismApi.UnmountImage.cs index 73b7af9..95527cd 100644 --- a/src/Microsoft.Dism/DismApi.UnmountImage.cs +++ b/src/Microsoft.Dism/DismApi.UnmountImage.cs @@ -77,43 +77,43 @@ public static Task UnmountImageAsync(string mountPath, bool commitChanges, IProg Task.Factory.StartNew( () => - { - try { - uint flags = commitChanges ? DISM_COMMIT_IMAGE : DISM_DISCARD_IMAGE; + try + { + uint flags = commitChanges ? DISM_COMMIT_IMAGE : DISM_DISCARD_IMAGE; - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - int hresult = NativeMethods.DismUnmountImage(mountPath, flags, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + int hresult = NativeMethods.DismUnmountImage(mountPath, flags, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - if (cancellationToken.IsCancellationRequested) + if (cancellationToken.IsCancellationRequested) + { + tcs.TrySetCanceled(cancellationToken); + } + else + { + DismUtilities.ThrowIfFail(hresult); + tcs.TrySetResult(true); + } + } + catch (OperationCanceledException) { tcs.TrySetCanceled(cancellationToken); } - else + catch (Exception ex) { - DismUtilities.ThrowIfFail(hresult); - tcs.TrySetResult(true); + tcs.TrySetException(ex); } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - cancellationToken, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + finally + { + ctsRegistration.Dispose(); + } + }, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); return tcs.Task; } From 79f90dff9fde1f79ddc334932eb98f34172f5191 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 29 Mar 2026 21:22:43 +0000 Subject: [PATCH 09/13] Fix SA1202: move public async methods before private sync methods the private sync helper methods in 4 files to satisfy SA1202 ('public' members should come before 'private' members): - DismApi.EnableFeature.cs - DismApi.MountImage.cs - DismApi.RemovePackage.cs - DismApi.SetEdition.cs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Rolling2405 <89894749+Rolling2405@users.noreply.github.com> --- src/Microsoft.Dism/DismApi.EnableFeature.cs | 74 ++++++++++----------- src/Microsoft.Dism/DismApi.MountImage.cs | 54 +++++++-------- src/Microsoft.Dism/DismApi.RemovePackage.cs | 36 +++++----- src/Microsoft.Dism/DismApi.SetEdition.cs | 40 +++++------ 4 files changed, 102 insertions(+), 102 deletions(-) diff --git a/src/Microsoft.Dism/DismApi.EnableFeature.cs b/src/Microsoft.Dism/DismApi.EnableFeature.cs index 2a1b154..b489fc3 100644 --- a/src/Microsoft.Dism/DismApi.EnableFeature.cs +++ b/src/Microsoft.Dism/DismApi.EnableFeature.cs @@ -207,43 +207,6 @@ public static void EnableFeature(DismSession session, string featureName, bool l EnableFeature(session, featureName, identifier: null, DismPackageIdentifier.None, limitAccess, enableAll, sourcePaths, progressCallback, userData); } - /// - /// Enables a feature from the specified package path. - /// - /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. - /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. - /// A package name or absolute path. - /// A DismPackageIdentifier value. - /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. - /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. - /// A list of source locations to check for files needed to enable the feature. - /// A progress callback method to invoke when progress is made. - /// Optional user data to pass to the DismProgressCallback method. - /// When a failure occurs. - private static void EnableFeature(DismSession session, string featureName, string? identifier, DismPackageIdentifier packageIdentifier, bool limitAccess, bool enableAll, List? sourcePaths, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) - { - // Get the list of source paths as an array - string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; - - // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); - - int hresult = NativeMethods.DismEnableFeature( - session: session, - featureName: featureName, - identifier: identifier, - packageIdentifier: identifier == null ? DismPackageIdentifier.None : packageIdentifier, - limitAccess: limitAccess, - sourcePaths: sourcePathsArray, - sourcePathCount: (uint)sourcePathsArray.Length, - enableAll: enableAll, - cancelEvent: progress.EventHandle, - progress: progress.DismProgressCallbackNative, - userData: IntPtr.Zero); - - DismUtilities.ThrowIfFail(hresult, session); - } - #if !NET40 /// /// Asynchronously enables a feature from the default package. @@ -357,6 +320,43 @@ private static Task EnableFeatureAsync(DismSession session, string featureName, } #endif + /// + /// Enables a feature from the specified package path. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// A package name or absolute path. + /// A DismPackageIdentifier value. + /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. + /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. + /// A list of source locations to check for files needed to enable the feature. + /// A progress callback method to invoke when progress is made. + /// Optional user data to pass to the DismProgressCallback method. + /// When a failure occurs. + private static void EnableFeature(DismSession session, string featureName, string? identifier, DismPackageIdentifier packageIdentifier, bool limitAccess, bool enableAll, List? sourcePaths, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) + { + // Get the list of source paths as an array + string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; + + // Create a DismProgress object to wrap the callback and allow cancellation + DismProgress progress = new DismProgress(progressCallback, userData); + + int hresult = NativeMethods.DismEnableFeature( + session: session, + featureName: featureName, + identifier: identifier, + packageIdentifier: identifier == null ? DismPackageIdentifier.None : packageIdentifier, + limitAccess: limitAccess, + sourcePaths: sourcePathsArray, + sourcePathCount: (uint)sourcePathsArray.Length, + enableAll: enableAll, + cancelEvent: progress.EventHandle, + progress: progress.DismProgressCallbackNative, + userData: IntPtr.Zero); + + DismUtilities.ThrowIfFail(hresult, session); + } + internal static partial class NativeMethods { /// diff --git a/src/Microsoft.Dism/DismApi.MountImage.cs b/src/Microsoft.Dism/DismApi.MountImage.cs index 7d267e5..da14a30 100644 --- a/src/Microsoft.Dism/DismApi.MountImage.cs +++ b/src/Microsoft.Dism/DismApi.MountImage.cs @@ -218,31 +218,6 @@ public static void MountImage(string imageFilePath, string mountPath, string? im MountImage(imageFilePath, mountPath, 0, imageName, DismImageIdentifier.ImageName, readOnly, options, progressCallback, userData); } - /// - /// Mounts a WIM or VHD image file to a specified location. - /// - /// The path to the WIM or VHD file on the local computer. A .wim, .vhd, or .vhdx file name extension is required. - /// The path of the location where the image should be mounted. This mount path must already exist on the computer. The Windows image in a .wim, .vhd, or .vhdx file can be mounted to an empty folder on an NTFS formatted drive. A Windows image in a .vhd or .vhdx file can also be mounted to an unassigned drive letter. You cannot mount an image to the root of the existing drive. - /// The index of the image in the WIM file that you want to mount. For a VHD file, you must specify an index of 1. - /// The name of the image that you want to mount. - /// A DismImageIdentifier Enumeration value such as DismImageIndex. - /// Specifies if the image should be mounted in read-only mode. - /// Specifies options to use when mounting an image. - /// A progress callback method to invoke when progress is made. - /// Optional user data to pass to the DismProgressCallback method. - private static void MountImage(string imageFilePath, string mountPath, int imageIndex, string? imageName, DismImageIdentifier imageIdentifier, bool readOnly, DismMountImageOptions options, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) - { - // Determine the flags to pass to the native call - uint flags = (readOnly ? DISM_MOUNT_READONLY : DISM_MOUNT_READWRITE) | (uint)options; - - // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); - - int hresult = NativeMethods.DismMountImage(imageFilePath, mountPath, (uint)imageIndex, imageName, imageIdentifier, flags, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); - - DismUtilities.ThrowIfFail(hresult); - } - #if !NET40 /// /// Asynchronously mounts a WIM or VHD image file to a specified location using an image index. @@ -257,7 +232,7 @@ private static void MountImage(string imageFilePath, string mountPath, int image /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. - public static Task MountImageAsync(string imageFilePath, string mountPath, int imageIndex, bool readOnly, DismMountImageOptions options = DismMountImageOptions.None, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task MountImageAsync(string imageFilePath, string mountPath, int imageIndex, bool readOnly, DismMountImageOptions options, IProgress? progress = null, CancellationToken cancellationToken = default) { return MountImageAsync(imageFilePath, mountPath, imageIndex, null, DismImageIdentifier.ImageIndex, readOnly, options, progress, cancellationToken); } @@ -275,7 +250,7 @@ public static Task MountImageAsync(string imageFilePath, string mountPath, int i /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. - public static Task MountImageAsync(string imageFilePath, string mountPath, string? imageName, bool readOnly, DismMountImageOptions options = DismMountImageOptions.None, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task MountImageAsync(string imageFilePath, string mountPath, string? imageName, bool readOnly, DismMountImageOptions options, IProgress? progress = null, CancellationToken cancellationToken = default) { return MountImageAsync(imageFilePath, mountPath, 0, imageName, DismImageIdentifier.ImageName, readOnly, options, progress, cancellationToken); } @@ -333,6 +308,31 @@ private static Task MountImageAsync(string imageFilePath, string mountPath, int } #endif + /// + /// Mounts a WIM or VHD image file to a specified location. + /// + /// The path to the WIM or VHD file on the local computer. A .wim, .vhd, or .vhdx file name extension is required. + /// The path of the location where the image should be mounted. This mount path must already exist on the computer. The Windows image in a .wim, .vhd, or .vhdx file can be mounted to an empty folder on an NTFS formatted drive. A Windows image in a .vhd or .vhdx file can also be mounted to an unassigned drive letter. You cannot mount an image to the root of the existing drive. + /// The index of the image in the WIM file that you want to mount. For a VHD file, you must specify an index of 1. + /// The name of the image that you want to mount. + /// A DismImageIdentifier Enumeration value such as DismImageIndex. + /// Specifies if the image should be mounted in read-only mode. + /// Specifies options to use when mounting an image. + /// A progress callback method to invoke when progress is made. + /// Optional user data to pass to the DismProgressCallback method. + private static void MountImage(string imageFilePath, string mountPath, int imageIndex, string? imageName, DismImageIdentifier imageIdentifier, bool readOnly, DismMountImageOptions options, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) + { + // Determine the flags to pass to the native call + uint flags = (readOnly ? DISM_MOUNT_READONLY : DISM_MOUNT_READWRITE) | (uint)options; + + // Create a DismProgress object to wrap the callback and allow cancellation + DismProgress progress = new DismProgress(progressCallback, userData); + + int hresult = NativeMethods.DismMountImage(imageFilePath, mountPath, (uint)imageIndex, imageName, imageIdentifier, flags, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); + + DismUtilities.ThrowIfFail(hresult); + } + internal static partial class NativeMethods { /// diff --git a/src/Microsoft.Dism/DismApi.RemovePackage.cs b/src/Microsoft.Dism/DismApi.RemovePackage.cs index e712507..9ffaaf1 100644 --- a/src/Microsoft.Dism/DismApi.RemovePackage.cs +++ b/src/Microsoft.Dism/DismApi.RemovePackage.cs @@ -94,24 +94,6 @@ public static void RemovePackageByPath(DismSession session, string packagePath, RemovePackage(session, packagePath, DismPackageIdentifier.Path, progressCallback, userData); } - /// - /// Removes a package from an image. - /// - /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. - /// Either an absolute path to a .cab file or the package name, depending on the PackageIdentifier parameter value. - /// A DismPackageIdentifier Enumeration. - /// A progress callback method to invoke when progress is made. - /// Optional user data to pass to the DismProgressCallback method. - private static void RemovePackage(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, Dism.DismProgressCallback? progressCallback, object? userData) - { - // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); - - int hresult = NativeMethods.DismRemovePackage(session, identifier, packageIdentifier, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); - - DismUtilities.ThrowIfFail(hresult, session); - } - #if !NET40 /// /// Asynchronously removes a package from an image by name. @@ -196,6 +178,24 @@ private static Task RemovePackageAsync(DismSession session, string identifier, D } #endif + /// + /// Removes a package from an image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// Either an absolute path to a .cab file or the package name, depending on the PackageIdentifier parameter value. + /// A DismPackageIdentifier Enumeration. + /// A progress callback method to invoke when progress is made. + /// Optional user data to pass to the DismProgressCallback method. + private static void RemovePackage(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, Dism.DismProgressCallback? progressCallback, object? userData) + { + // Create a DismProgress object to wrap the callback and allow cancellation + DismProgress progress = new DismProgress(progressCallback, userData); + + int hresult = NativeMethods.DismRemovePackage(session, identifier, packageIdentifier, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); + + DismUtilities.ThrowIfFail(hresult, session); + } + internal static partial class NativeMethods { /// diff --git a/src/Microsoft.Dism/DismApi.SetEdition.cs b/src/Microsoft.Dism/DismApi.SetEdition.cs index 0003f40..49aa82d 100644 --- a/src/Microsoft.Dism/DismApi.SetEdition.cs +++ b/src/Microsoft.Dism/DismApi.SetEdition.cs @@ -93,26 +93,6 @@ public static void SetEditionAndProductKey(DismSession session, string editionId SetEdition(session, editionId, productKey, progressCallback, userData); } - /// - /// Changes an offline Windows image to a higher edition and optionaly sets the product key. - /// - /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. - /// The edition to set the image to. - /// Optional. A product key for the specified edition. - /// A progress callback method to invoke when progress is made. - /// Optional user data to pass to the DismProgressCallback method. - /// When a failure occurs. - /// When the operation requires a reboot to complete. - private static void SetEdition(DismSession session, string editionId, string? productKey, Dism.DismProgressCallback? progressCallback, object? userData) - { - // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); - - int hresult = NativeMethods.DismSetEdition(session, editionId, productKey, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); - - DismUtilities.ThrowIfFail(hresult, session); - } - #if !NET40 /// /// Asynchronously changes an offline Windows image to a higher edition. @@ -198,6 +178,26 @@ private static Task SetEditionAsync(DismSession session, string editionId, strin } #endif + /// + /// Changes an offline Windows image to a higher edition and optionaly sets the product key. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. + /// The edition to set the image to. + /// Optional. A product key for the specified edition. + /// A progress callback method to invoke when progress is made. + /// Optional user data to pass to the DismProgressCallback method. + /// When a failure occurs. + /// When the operation requires a reboot to complete. + private static void SetEdition(DismSession session, string editionId, string? productKey, Dism.DismProgressCallback? progressCallback, object? userData) + { + // Create a DismProgress object to wrap the callback and allow cancellation + DismProgress progress = new DismProgress(progressCallback, userData); + + int hresult = NativeMethods.DismSetEdition(session, editionId, productKey, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); + + DismUtilities.ThrowIfFail(hresult, session); + } + internal static partial class NativeMethods { /// From 26ace5408c77ac2dab7bde5fa087981be96ba7da Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 29 Mar 2026 21:26:48 +0000 Subject: [PATCH 10/13] Fix RS0026 for MountImageAsync, add PublicAPI declarations, suppress RS0016/RS0017 for net40 - Remove optional parameter defaults from MountImageAsync overloads to fix RS0026 - Add all 17 public async method signatures to PublicAPI.Unshipped.txt Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Rolling2405 <89894749+Rolling2405@users.noreply.github.com> --- src/Microsoft.Dism/DismApi.MountImage.cs | 4 ++-- src/Microsoft.Dism/Microsoft.Dism.csproj | 1 + src/Microsoft.Dism/PublicAPI.Unshipped.txt | 17 +++++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Dism/DismApi.MountImage.cs b/src/Microsoft.Dism/DismApi.MountImage.cs index da14a30..92cd865 100644 --- a/src/Microsoft.Dism/DismApi.MountImage.cs +++ b/src/Microsoft.Dism/DismApi.MountImage.cs @@ -232,7 +232,7 @@ public static void MountImage(string imageFilePath, string mountPath, string? im /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. - public static Task MountImageAsync(string imageFilePath, string mountPath, int imageIndex, bool readOnly, DismMountImageOptions options, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task MountImageAsync(string imageFilePath, string mountPath, int imageIndex, bool readOnly, DismMountImageOptions options, IProgress? progress, CancellationToken cancellationToken) { return MountImageAsync(imageFilePath, mountPath, imageIndex, null, DismImageIdentifier.ImageIndex, readOnly, options, progress, cancellationToken); } @@ -250,7 +250,7 @@ public static Task MountImageAsync(string imageFilePath, string mountPath, int i /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. - public static Task MountImageAsync(string imageFilePath, string mountPath, string? imageName, bool readOnly, DismMountImageOptions options, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task MountImageAsync(string imageFilePath, string mountPath, string? imageName, bool readOnly, DismMountImageOptions options, IProgress? progress, CancellationToken cancellationToken) { return MountImageAsync(imageFilePath, mountPath, 0, imageName, DismImageIdentifier.ImageName, readOnly, options, progress, cancellationToken); } diff --git a/src/Microsoft.Dism/Microsoft.Dism.csproj b/src/Microsoft.Dism/Microsoft.Dism.csproj index 3a9de3c..39b9aad 100644 --- a/src/Microsoft.Dism/Microsoft.Dism.csproj +++ b/src/Microsoft.Dism/Microsoft.Dism.csproj @@ -10,6 +10,7 @@ $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb true true + $(NoWarn);RS0016;RS0017 diff --git a/src/Microsoft.Dism/PublicAPI.Unshipped.txt b/src/Microsoft.Dism/PublicAPI.Unshipped.txt index ab058de..75bba0a 100644 --- a/src/Microsoft.Dism/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Dism/PublicAPI.Unshipped.txt @@ -1 +1,18 @@ #nullable enable +static Microsoft.Dism.DismApi.AddCapabilityAsync(Microsoft.Dism.DismSession! session, string! capabilityName, bool limitAccess, System.Collections.Generic.List? sourcePaths, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.AddPackageAsync(Microsoft.Dism.DismSession! session, string! packagePath, bool ignoreCheck, bool preventPending, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.CheckImageHealthAsync(Microsoft.Dism.DismSession! session, bool scanImage, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.CommitImageAsync(Microsoft.Dism.DismSession! session, bool discardChanges, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.DisableFeatureAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packageName, bool removePayload, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.EnableFeatureAsync(Microsoft.Dism.DismSession! session, string! featureName, bool limitAccess, bool enableAll, System.Collections.Generic.List? sourcePaths = null, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.EnableFeatureByPackageNameAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packageName, bool limitAccess, bool enableAll, System.Collections.Generic.List? sourcePaths = null, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.EnableFeatureByPackagePathAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packagePath, bool limitAccess, bool enableAll, System.Collections.Generic.List? sourcePaths = null, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.MountImageAsync(string! imageFilePath, string! mountPath, int imageIndex, bool readOnly, Microsoft.Dism.DismMountImageOptions options, System.IProgress? progress, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.MountImageAsync(string! imageFilePath, string! mountPath, string? imageName, bool readOnly, Microsoft.Dism.DismMountImageOptions options, System.IProgress? progress, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RemoveCapabilityAsync(Microsoft.Dism.DismSession! session, string! capabilityName, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RemovePackageByNameAsync(Microsoft.Dism.DismSession! session, string! packageName, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RemovePackageByPathAsync(Microsoft.Dism.DismSession! session, string! packagePath, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RestoreImageHealthAsync(Microsoft.Dism.DismSession! session, bool limitAccess, System.Collections.Generic.List? sourcePaths = null, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.SetEditionAndProductKeyAsync(Microsoft.Dism.DismSession! session, string! editionId, string! productKey, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.SetEditionAsync(Microsoft.Dism.DismSession! session, string! editionId, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.UnmountImageAsync(string! mountPath, bool commitChanges, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! From f19d7c6c4d0fd9de9012e3ab853915a326d63319 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 30 Mar 2026 01:50:45 +0000 Subject: [PATCH 11/13] Add async tests and fix cancellation bug in Task.Factory.StartNew Agent-Logs-Url: https://github.com/Rolling2405/ManagedDism/sessions/d5267b48-44f8-4364-ac85-dab68ef56967 Co-authored-by: Rolling2405 <89894749+Rolling2405@users.noreply.github.com> --- .../AddCapabilityAsyncTest.cs | 83 ++++++++++ .../AddPackageAsyncTest.cs | 83 ++++++++++ .../CheckImageHealthAsyncTest.cs | 98 ++++++++++++ .../CommitImageAsyncTest.cs | 83 ++++++++++ .../DisableFeatureAsyncTest.cs | 83 ++++++++++ .../EnableFeatureAsyncTest.cs | 125 +++++++++++++++ .../MountImageAsyncTest.cs | 142 ++++++++++++++++++ .../RemoveCapabilityAsyncTest.cs | 83 ++++++++++ .../RemovePackageAsyncTest.cs | 104 +++++++++++++ .../RestoreImageHealthAsyncTest.cs | 79 ++++++++++ .../SetEditionAsyncTest.cs | 101 +++++++++++++ .../UnmountImageAsyncTest.cs | 109 ++++++++++++++ src/Microsoft.Dism/DismApi.AddCapability.cs | 2 +- src/Microsoft.Dism/DismApi.AddPackage.cs | 2 +- .../DismApi.CheckImageHealth.cs | 2 +- src/Microsoft.Dism/DismApi.CommitImage.cs | 2 +- src/Microsoft.Dism/DismApi.DisableFeature.cs | 2 +- src/Microsoft.Dism/DismApi.EnableFeature.cs | 2 +- src/Microsoft.Dism/DismApi.MountImage.cs | 2 +- .../DismApi.RemoveCapability.cs | 2 +- src/Microsoft.Dism/DismApi.RemovePackage.cs | 2 +- .../DismApi.RestoreImageHealth.cs | 2 +- src/Microsoft.Dism/DismApi.SetEdition.cs | 2 +- src/Microsoft.Dism/DismApi.UnmountImage.cs | 2 +- 24 files changed, 1185 insertions(+), 12 deletions(-) create mode 100644 src/Microsoft.Dism.Tests/AddCapabilityAsyncTest.cs create mode 100644 src/Microsoft.Dism.Tests/AddPackageAsyncTest.cs create mode 100644 src/Microsoft.Dism.Tests/CheckImageHealthAsyncTest.cs create mode 100644 src/Microsoft.Dism.Tests/CommitImageAsyncTest.cs create mode 100644 src/Microsoft.Dism.Tests/DisableFeatureAsyncTest.cs create mode 100644 src/Microsoft.Dism.Tests/EnableFeatureAsyncTest.cs create mode 100644 src/Microsoft.Dism.Tests/MountImageAsyncTest.cs create mode 100644 src/Microsoft.Dism.Tests/RemoveCapabilityAsyncTest.cs create mode 100644 src/Microsoft.Dism.Tests/RemovePackageAsyncTest.cs create mode 100644 src/Microsoft.Dism.Tests/RestoreImageHealthAsyncTest.cs create mode 100644 src/Microsoft.Dism.Tests/SetEditionAsyncTest.cs create mode 100644 src/Microsoft.Dism.Tests/UnmountImageAsyncTest.cs diff --git a/src/Microsoft.Dism.Tests/AddCapabilityAsyncTest.cs b/src/Microsoft.Dism.Tests/AddCapabilityAsyncTest.cs new file mode 100644 index 0000000..4cccd23 --- /dev/null +++ b/src/Microsoft.Dism.Tests/AddCapabilityAsyncTest.cs @@ -0,0 +1,83 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. +#if !NETFRAMEWORK +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class AddCapabilityAsyncTest : DismTestBase + { + public AddCapabilityAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task AddCapabilityAsyncCancellation() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.AddCapabilityAsync(session, "FakeCapability", limitAccess: true, sourcePaths: null, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task AddCapabilityAsyncWithProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + + var progress = new SynchronousProgress(_ => + { + cts.Cancel(); + }); + + try + { + await DismApi.AddCapabilityAsync(session, "FakeCapability", limitAccess: true, sourcePaths: null, progress: progress, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + } + catch (DismException) + { + // Expected when the capability does not exist + } + + // Progress may not be called for an invalid capability, so we just verify no hang occurred + } + + private sealed class SynchronousProgress : IProgress + { + private readonly Action _handler; + + public SynchronousProgress(Action handler) + { + _handler = handler; + } + + public void Report(T value) + { + _handler(value); + } + } + } +} +#endif diff --git a/src/Microsoft.Dism.Tests/AddPackageAsyncTest.cs b/src/Microsoft.Dism.Tests/AddPackageAsyncTest.cs new file mode 100644 index 0000000..87bab3c --- /dev/null +++ b/src/Microsoft.Dism.Tests/AddPackageAsyncTest.cs @@ -0,0 +1,83 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. +#if !NETFRAMEWORK +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class AddPackageAsyncTest : DismTestBase + { + public AddPackageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task AddPackageAsyncCancellation() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.AddPackageAsync(session, "nonexistent.cab", ignoreCheck: false, preventPending: false, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task AddPackageAsyncWithProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + + var progress = new SynchronousProgress(_ => + { + cts.Cancel(); + }); + + try + { + await DismApi.AddPackageAsync(session, "nonexistent.cab", ignoreCheck: false, preventPending: false, progress: progress, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + } + catch (DismException) + { + // Expected when the package does not exist + } + + // Progress may not be called for an invalid package, so we just verify no hang occurred + } + + private sealed class SynchronousProgress : IProgress + { + private readonly Action _handler; + + public SynchronousProgress(Action handler) + { + _handler = handler; + } + + public void Report(T value) + { + _handler(value); + } + } + } +} +#endif diff --git a/src/Microsoft.Dism.Tests/CheckImageHealthAsyncTest.cs b/src/Microsoft.Dism.Tests/CheckImageHealthAsyncTest.cs new file mode 100644 index 0000000..f3de6c8 --- /dev/null +++ b/src/Microsoft.Dism.Tests/CheckImageHealthAsyncTest.cs @@ -0,0 +1,98 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +#if !NETFRAMEWORK +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class CheckImageHealthAsyncTest : DismTestBase + { + public CheckImageHealthAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task CheckImageHealthAsyncOnlineSession() + { + using DismSession session = DismApi.OpenOnlineSession(); + + DismImageHealthState imageHealthState = await DismApi.CheckImageHealthAsync(session, scanImage: false, cancellationToken: TestContext.Current.CancellationToken); + + imageHealthState.ShouldBe(DismImageHealthState.Healthy); + } + + [Fact] + public async Task CheckImageHealthAsyncCancellation() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.CheckImageHealthAsync(session, scanImage: false, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task CheckImageHealthAsyncWithProgress() + { + int current = -1; + int total = -1; + + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + + var progress = new SynchronousProgress(p => + { + current = p.Current; + total = p.Total; + + // Cancel the operation, otherwise it takes ~1 min + cts.Cancel(); + }); + + try + { + await DismApi.CheckImageHealthAsync(session, scanImage: true, progress: progress, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + } + + current.ShouldBe(50); + total.ShouldBeGreaterThanOrEqualTo(1000); + } + + private sealed class SynchronousProgress : IProgress + { + private readonly Action _handler; + + public SynchronousProgress(Action handler) + { + _handler = handler; + } + + public void Report(T value) + { + _handler(value); + } + } + } +} +#endif diff --git a/src/Microsoft.Dism.Tests/CommitImageAsyncTest.cs b/src/Microsoft.Dism.Tests/CommitImageAsyncTest.cs new file mode 100644 index 0000000..d788c61 --- /dev/null +++ b/src/Microsoft.Dism.Tests/CommitImageAsyncTest.cs @@ -0,0 +1,83 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. +#if !NETFRAMEWORK +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class CommitImageAsyncTest : DismInstallWimTestBase + { + public CommitImageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task CommitImageAsyncCancellation() + { + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.CommitImageAsync(Session, discardChanges: true, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task CommitImageAsyncWithProgress() + { + using var cts = new CancellationTokenSource(); + + var progress = new SynchronousProgress(_ => + { + cts.Cancel(); + }); + + try + { + await DismApi.CommitImageAsync(Session, discardChanges: true, progress: progress, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + } + + // Progress may or may not be called depending on whether changes exist to commit + } + + [Fact] + public async Task CommitImageAsyncHappyPath() + { + await DismApi.CommitImageAsync(Session, discardChanges: true, cancellationToken: TestContext.Current.CancellationToken); + } + + private sealed class SynchronousProgress : IProgress + { + private readonly Action _handler; + + public SynchronousProgress(Action handler) + { + _handler = handler; + } + + public void Report(T value) + { + _handler(value); + } + } + } +} +#endif diff --git a/src/Microsoft.Dism.Tests/DisableFeatureAsyncTest.cs b/src/Microsoft.Dism.Tests/DisableFeatureAsyncTest.cs new file mode 100644 index 0000000..1488787 --- /dev/null +++ b/src/Microsoft.Dism.Tests/DisableFeatureAsyncTest.cs @@ -0,0 +1,83 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. +#if !NETFRAMEWORK +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class DisableFeatureAsyncTest : DismTestBase + { + public DisableFeatureAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task DisableFeatureAsyncCancellation() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.DisableFeatureAsync(session, "FakeFeature", packageName: string.Empty, removePayload: false, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task DisableFeatureAsyncWithProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + + var progress = new SynchronousProgress(_ => + { + cts.Cancel(); + }); + + try + { + await DismApi.DisableFeatureAsync(session, "FakeFeature", packageName: string.Empty, removePayload: false, progress: progress, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + } + catch (DismException) + { + // Expected when the feature does not exist + } + + // Progress may not be called for an invalid feature, so we just verify no hang occurred + } + + private sealed class SynchronousProgress : IProgress + { + private readonly Action _handler; + + public SynchronousProgress(Action handler) + { + _handler = handler; + } + + public void Report(T value) + { + _handler(value); + } + } + } +} +#endif diff --git a/src/Microsoft.Dism.Tests/EnableFeatureAsyncTest.cs b/src/Microsoft.Dism.Tests/EnableFeatureAsyncTest.cs new file mode 100644 index 0000000..755f369 --- /dev/null +++ b/src/Microsoft.Dism.Tests/EnableFeatureAsyncTest.cs @@ -0,0 +1,125 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. +#if !NETFRAMEWORK +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class EnableFeatureAsyncTest : DismTestBase + { + public EnableFeatureAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task EnableFeatureAsyncCancellation() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.EnableFeatureAsync(session, "FakeFeature", limitAccess: true, enableAll: false, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task EnableFeatureByPackageNameAsyncCancellation() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.EnableFeatureByPackageNameAsync(session, "FakeFeature", "FakePackage", limitAccess: true, enableAll: false, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task EnableFeatureByPackagePathAsyncCancellation() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.EnableFeatureByPackagePathAsync(session, "FakeFeature", "FakePackage.cab", limitAccess: true, enableAll: false, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task EnableFeatureAsyncWithProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + + var progress = new SynchronousProgress(_ => + { + cts.Cancel(); + }); + + try + { + await DismApi.EnableFeatureAsync(session, "FakeFeature", limitAccess: true, enableAll: false, progress: progress, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + } + catch (DismException) + { + // Expected when the feature does not exist + } + + // Progress may not be called for an invalid feature, so we just verify no hang occurred + } + + private sealed class SynchronousProgress : IProgress + { + private readonly Action _handler; + + public SynchronousProgress(Action handler) + { + _handler = handler; + } + + public void Report(T value) + { + _handler(value); + } + } + } +} +#endif diff --git a/src/Microsoft.Dism.Tests/MountImageAsyncTest.cs b/src/Microsoft.Dism.Tests/MountImageAsyncTest.cs new file mode 100644 index 0000000..c7ded4e --- /dev/null +++ b/src/Microsoft.Dism.Tests/MountImageAsyncTest.cs @@ -0,0 +1,142 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +#if !NETFRAMEWORK +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class MountImageAsyncTest : DismTestBase + { + public MountImageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task MountImageAsyncByIndexHappyPath() + { + foreach (DismMountedImageInfo mountedImageInfo in DismApi.GetMountedImages()) + { + DismApi.UnmountImage(mountedImageInfo.MountPath, false); + } + + DismApi.CleanupMountpoints(); + + try + { + await DismApi.MountImageAsync(InstallWimPath.FullName, MountPath.FullName, imageIndex: 1, readOnly: true, options: DismMountImageOptions.None, progress: null, cancellationToken: CancellationToken.None); + } + finally + { + try + { + DismApi.UnmountImage(MountPath.FullName, commitChanges: false); + } + catch + { + // Best effort cleanup + } + } + } + + [Fact] + public async Task MountImageAsyncByIndexCancellation() + { + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.MountImageAsync(InstallWimPath.FullName, MountPath.FullName, imageIndex: 1, readOnly: true, options: DismMountImageOptions.None, progress: null, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task MountImageAsyncByNameCancellation() + { + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.MountImageAsync(InstallWimPath.FullName, MountPath.FullName, imageName: "FakeImage", readOnly: true, options: DismMountImageOptions.None, progress: null, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task MountImageAsyncWithProgress() + { + bool progressCalled = false; + + foreach (DismMountedImageInfo mountedImageInfo in DismApi.GetMountedImages()) + { + DismApi.UnmountImage(mountedImageInfo.MountPath, false); + } + + DismApi.CleanupMountpoints(); + + using var cts = new CancellationTokenSource(); + + var progress = new SynchronousProgress(_ => + { + progressCalled = true; + }); + + try + { + await DismApi.MountImageAsync(InstallWimPath.FullName, MountPath.FullName, imageIndex: 1, readOnly: true, options: DismMountImageOptions.None, progress: progress, cancellationToken: cts.Token); + } + finally + { + try + { + DismApi.UnmountImage(MountPath.FullName, commitChanges: false); + } + catch + { + // Best effort cleanup + } + } + + progressCalled.ShouldBeTrue(); + } + + private sealed class SynchronousProgress : IProgress + { + private readonly Action _handler; + + public SynchronousProgress(Action handler) + { + _handler = handler; + } + + public void Report(T value) + { + _handler(value); + } + } + } +} +#endif diff --git a/src/Microsoft.Dism.Tests/RemoveCapabilityAsyncTest.cs b/src/Microsoft.Dism.Tests/RemoveCapabilityAsyncTest.cs new file mode 100644 index 0000000..802aab9 --- /dev/null +++ b/src/Microsoft.Dism.Tests/RemoveCapabilityAsyncTest.cs @@ -0,0 +1,83 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. +#if !NETFRAMEWORK +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class RemoveCapabilityAsyncTest : DismTestBase + { + public RemoveCapabilityAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task RemoveCapabilityAsyncCancellation() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.RemoveCapabilityAsync(session, "FakeCapability", cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task RemoveCapabilityAsyncWithProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + + var progress = new SynchronousProgress(_ => + { + cts.Cancel(); + }); + + try + { + await DismApi.RemoveCapabilityAsync(session, "FakeCapability", progress: progress, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + } + catch (DismException) + { + // Expected when the capability does not exist + } + + // Progress may not be called for an invalid capability, so we just verify no hang occurred + } + + private sealed class SynchronousProgress : IProgress + { + private readonly Action _handler; + + public SynchronousProgress(Action handler) + { + _handler = handler; + } + + public void Report(T value) + { + _handler(value); + } + } + } +} +#endif diff --git a/src/Microsoft.Dism.Tests/RemovePackageAsyncTest.cs b/src/Microsoft.Dism.Tests/RemovePackageAsyncTest.cs new file mode 100644 index 0000000..ec8ec39 --- /dev/null +++ b/src/Microsoft.Dism.Tests/RemovePackageAsyncTest.cs @@ -0,0 +1,104 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. +#if !NETFRAMEWORK +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class RemovePackageAsyncTest : DismTestBase + { + public RemovePackageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task RemovePackageByNameAsyncCancellation() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.RemovePackageByNameAsync(session, "FakePackage", cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task RemovePackageByPathAsyncCancellation() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.RemovePackageByPathAsync(session, "nonexistent.cab", cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task RemovePackageByNameAsyncWithProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + + var progress = new SynchronousProgress(_ => + { + cts.Cancel(); + }); + + try + { + await DismApi.RemovePackageByNameAsync(session, "FakePackage", progress: progress, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + } + catch (DismException) + { + // Expected when the package does not exist + } + + // Progress may not be called for an invalid package, so we just verify no hang occurred + } + + private sealed class SynchronousProgress : IProgress + { + private readonly Action _handler; + + public SynchronousProgress(Action handler) + { + _handler = handler; + } + + public void Report(T value) + { + _handler(value); + } + } + } +} +#endif diff --git a/src/Microsoft.Dism.Tests/RestoreImageHealthAsyncTest.cs b/src/Microsoft.Dism.Tests/RestoreImageHealthAsyncTest.cs new file mode 100644 index 0000000..a2b0c5d --- /dev/null +++ b/src/Microsoft.Dism.Tests/RestoreImageHealthAsyncTest.cs @@ -0,0 +1,79 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. +#if !NETFRAMEWORK +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class RestoreImageHealthAsyncTest : DismTestBase + { + public RestoreImageHealthAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task RestoreImageHealthAsyncCancellation() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.RestoreImageHealthAsync(session, limitAccess: true, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task RestoreImageHealthAsyncWithProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(); + + var progress = new SynchronousProgress(_ => + { + cts.Cancel(); + }); + + try + { + await DismApi.RestoreImageHealthAsync(session, limitAccess: true, progress: progress, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + } + + // Progress may or may not be called depending on image state, so we just verify no hang occurred + } + + private sealed class SynchronousProgress : IProgress + { + private readonly Action _handler; + + public SynchronousProgress(Action handler) + { + _handler = handler; + } + + public void Report(T value) + { + _handler(value); + } + } + } +} +#endif diff --git a/src/Microsoft.Dism.Tests/SetEditionAsyncTest.cs b/src/Microsoft.Dism.Tests/SetEditionAsyncTest.cs new file mode 100644 index 0000000..85b8391 --- /dev/null +++ b/src/Microsoft.Dism.Tests/SetEditionAsyncTest.cs @@ -0,0 +1,101 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. +#if !NETFRAMEWORK +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class SetEditionAsyncTest : DismInstallWimTestBase + { + public SetEditionAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task SetEditionAsyncCancellation() + { + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.SetEditionAsync(Session, "FakeEdition", cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task SetEditionAndProductKeyAsyncCancellation() + { + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.SetEditionAndProductKeyAsync(Session, "FakeEdition", "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX", cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task SetEditionAsyncWithProgress() + { + using var cts = new CancellationTokenSource(); + + var progress = new SynchronousProgress(_ => + { + cts.Cancel(); + }); + + try + { + await DismApi.SetEditionAsync(Session, "FakeEdition", progress: progress, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + } + catch (DismException) + { + // Expected when the edition does not exist + } + + // Progress may not be called for an invalid edition, so we just verify no hang occurred + } + + private sealed class SynchronousProgress : IProgress + { + private readonly Action _handler; + + public SynchronousProgress(Action handler) + { + _handler = handler; + } + + public void Report(T value) + { + _handler(value); + } + } + } +} +#endif diff --git a/src/Microsoft.Dism.Tests/UnmountImageAsyncTest.cs b/src/Microsoft.Dism.Tests/UnmountImageAsyncTest.cs new file mode 100644 index 0000000..cca5761 --- /dev/null +++ b/src/Microsoft.Dism.Tests/UnmountImageAsyncTest.cs @@ -0,0 +1,109 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. +#if !NETFRAMEWORK +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class UnmountImageAsyncTest : DismTestBase + { + public UnmountImageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task UnmountImageAsyncCancellation() + { + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.UnmountImageAsync(MountPath.FullName, commitChanges: false, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task UnmountImageAsyncWithProgress() + { + // Mount an image first so we can unmount it + foreach (DismMountedImageInfo mountedImageInfo in DismApi.GetMountedImages()) + { + DismApi.UnmountImage(mountedImageInfo.MountPath, false); + } + + DismApi.CleanupMountpoints(); + DismApi.MountImage(InstallWimPath.FullName, MountPath.FullName, 1); + + using var cts = new CancellationTokenSource(); + + var progress = new SynchronousProgress(_ => + { + }); + + try + { + await DismApi.UnmountImageAsync(MountPath.FullName, commitChanges: false, progress: progress, cancellationToken: cts.Token); + } + catch (DismException) + { + // Attempt to clean up + try + { + DismApi.UnmountImage(MountPath.FullName, commitChanges: false); + } + catch + { + // Best effort cleanup + } + } + + // Progress may or may not be called depending on image size + } + + [Fact] + public async Task UnmountImageAsyncHappyPath() + { + // Mount an image first so we can unmount it + foreach (DismMountedImageInfo mountedImageInfo in DismApi.GetMountedImages()) + { + DismApi.UnmountImage(mountedImageInfo.MountPath, false); + } + + DismApi.CleanupMountpoints(); + DismApi.MountImage(InstallWimPath.FullName, MountPath.FullName, 1); + + await DismApi.UnmountImageAsync(MountPath.FullName, commitChanges: false, cancellationToken: TestContext.Current.CancellationToken); + } + + private sealed class SynchronousProgress : IProgress + { + private readonly Action _handler; + + public SynchronousProgress(Action handler) + { + _handler = handler; + } + + public void Report(T value) + { + _handler(value); + } + } + } +} +#endif diff --git a/src/Microsoft.Dism/DismApi.AddCapability.cs b/src/Microsoft.Dism/DismApi.AddCapability.cs index da26570..c5949b5 100644 --- a/src/Microsoft.Dism/DismApi.AddCapability.cs +++ b/src/Microsoft.Dism/DismApi.AddCapability.cs @@ -121,7 +121,7 @@ public static Task AddCapabilityAsync(DismSession session, string capabilityName ctsRegistration.Dispose(); } }, - cancellationToken, + CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); diff --git a/src/Microsoft.Dism/DismApi.AddPackage.cs b/src/Microsoft.Dism/DismApi.AddPackage.cs index 38fae3f..5d2f01a 100644 --- a/src/Microsoft.Dism/DismApi.AddPackage.cs +++ b/src/Microsoft.Dism/DismApi.AddPackage.cs @@ -122,7 +122,7 @@ public static Task AddPackageAsync(DismSession session, string packagePath, bool ctsRegistration.Dispose(); } }, - cancellationToken, + CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); diff --git a/src/Microsoft.Dism/DismApi.CheckImageHealth.cs b/src/Microsoft.Dism/DismApi.CheckImageHealth.cs index 84b667a..5622326 100644 --- a/src/Microsoft.Dism/DismApi.CheckImageHealth.cs +++ b/src/Microsoft.Dism/DismApi.CheckImageHealth.cs @@ -111,7 +111,7 @@ public static Task CheckImageHealthAsync(DismSession sessi ctsRegistration.Dispose(); } }, - cancellationToken, + CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); diff --git a/src/Microsoft.Dism/DismApi.CommitImage.cs b/src/Microsoft.Dism/DismApi.CommitImage.cs index cd0aa76..0fb6bbc 100644 --- a/src/Microsoft.Dism/DismApi.CommitImage.cs +++ b/src/Microsoft.Dism/DismApi.CommitImage.cs @@ -111,7 +111,7 @@ public static Task CommitImageAsync(DismSession session, bool discardChanges, IP ctsRegistration.Dispose(); } }, - cancellationToken, + CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); diff --git a/src/Microsoft.Dism/DismApi.DisableFeature.cs b/src/Microsoft.Dism/DismApi.DisableFeature.cs index 9be4485..bf1f86b 100644 --- a/src/Microsoft.Dism/DismApi.DisableFeature.cs +++ b/src/Microsoft.Dism/DismApi.DisableFeature.cs @@ -126,7 +126,7 @@ public static Task DisableFeatureAsync(DismSession session, string featureName, ctsRegistration.Dispose(); } }, - cancellationToken, + CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); diff --git a/src/Microsoft.Dism/DismApi.EnableFeature.cs b/src/Microsoft.Dism/DismApi.EnableFeature.cs index b489fc3..d2652e8 100644 --- a/src/Microsoft.Dism/DismApi.EnableFeature.cs +++ b/src/Microsoft.Dism/DismApi.EnableFeature.cs @@ -312,7 +312,7 @@ private static Task EnableFeatureAsync(DismSession session, string featureName, ctsRegistration.Dispose(); } }, - cancellationToken, + CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); diff --git a/src/Microsoft.Dism/DismApi.MountImage.cs b/src/Microsoft.Dism/DismApi.MountImage.cs index 92cd865..d11adf4 100644 --- a/src/Microsoft.Dism/DismApi.MountImage.cs +++ b/src/Microsoft.Dism/DismApi.MountImage.cs @@ -300,7 +300,7 @@ private static Task MountImageAsync(string imageFilePath, string mountPath, int ctsRegistration.Dispose(); } }, - cancellationToken, + CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); diff --git a/src/Microsoft.Dism/DismApi.RemoveCapability.cs b/src/Microsoft.Dism/DismApi.RemoveCapability.cs index e296a04..731e059 100644 --- a/src/Microsoft.Dism/DismApi.RemoveCapability.cs +++ b/src/Microsoft.Dism/DismApi.RemoveCapability.cs @@ -96,7 +96,7 @@ public static Task RemoveCapabilityAsync(DismSession session, string capabilityN ctsRegistration.Dispose(); } }, - cancellationToken, + CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); diff --git a/src/Microsoft.Dism/DismApi.RemovePackage.cs b/src/Microsoft.Dism/DismApi.RemovePackage.cs index 9ffaaf1..fa998c9 100644 --- a/src/Microsoft.Dism/DismApi.RemovePackage.cs +++ b/src/Microsoft.Dism/DismApi.RemovePackage.cs @@ -170,7 +170,7 @@ private static Task RemovePackageAsync(DismSession session, string identifier, D ctsRegistration.Dispose(); } }, - cancellationToken, + CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); diff --git a/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs b/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs index ec515de..e7501ae 100644 --- a/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs +++ b/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs @@ -132,7 +132,7 @@ public static Task RestoreImageHealthAsync(DismSession session, bool limitAccess ctsRegistration.Dispose(); } }, - cancellationToken, + CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); diff --git a/src/Microsoft.Dism/DismApi.SetEdition.cs b/src/Microsoft.Dism/DismApi.SetEdition.cs index 49aa82d..e60d09c 100644 --- a/src/Microsoft.Dism/DismApi.SetEdition.cs +++ b/src/Microsoft.Dism/DismApi.SetEdition.cs @@ -170,7 +170,7 @@ private static Task SetEditionAsync(DismSession session, string editionId, strin ctsRegistration.Dispose(); } }, - cancellationToken, + CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); diff --git a/src/Microsoft.Dism/DismApi.UnmountImage.cs b/src/Microsoft.Dism/DismApi.UnmountImage.cs index 95527cd..2a86b41 100644 --- a/src/Microsoft.Dism/DismApi.UnmountImage.cs +++ b/src/Microsoft.Dism/DismApi.UnmountImage.cs @@ -111,7 +111,7 @@ public static Task UnmountImageAsync(string mountPath, bool commitChanges, IProg ctsRegistration.Dispose(); } }, - cancellationToken, + CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); From 7efd06d0a0f7176a48653626ae7c763813e979ea Mon Sep 17 00:00:00 2001 From: Jeff Kluge Date: Mon, 30 Mar 2026 10:46:26 -0700 Subject: [PATCH 12/13] Migrate from StyleCop to EditorConfig --- .editorconfig | 113 ++++++++++++++++++ .gitignore | 5 +- Directory.Packages.props | 6 +- Microsoft.Dism.sln | 5 +- .../AddCapabilityAsyncTest.cs | 6 +- .../AddPackageAsyncTest.cs | 6 +- src/Microsoft.Dism.Tests/ApplyUnattendTest.cs | 2 +- .../CheckImageHealthAsyncTest.cs | 6 +- .../CommitImageAsyncTest.cs | 6 +- .../DisableFeatureAsyncTest.cs | 6 +- .../DismAppxPackageTest.cs | 2 +- .../DismCapabilityInfoTest.cs | 8 +- .../DismCapabilityTest.cs | 2 +- .../DismCollectionTest.cs | 2 +- .../DismCustomPropertyTest.cs | 2 +- .../DismDriverPackageTest.cs | 2 +- src/Microsoft.Dism.Tests/DismDriverTest.cs | 2 +- .../DismFeatureInfoTest.cs | 10 +- src/Microsoft.Dism.Tests/DismFeatureTest.cs | 2 +- src/Microsoft.Dism.Tests/DismImageInfoTest.cs | 8 +- .../DismInitializeTest.cs | 4 +- .../DismMountedImageInfoTest.cs | 2 +- .../DismPackageInfoExTest.cs | 13 +- .../DismPackageInfoTest.cs | 16 +-- src/Microsoft.Dism.Tests/DismPackageTest.cs | 2 +- src/Microsoft.Dism.Tests/DismSessionTest.cs | 2 +- .../DismWimCustomizedInfoTest.cs | 4 +- .../EnableFeatureAsyncTest.cs | 10 +- src/Microsoft.Dism.Tests/ExtensionMethods.cs | 2 +- .../MountImageAsyncTest.cs | 8 +- .../RemoveCapabilityAsyncTest.cs | 6 +- .../RemovePackageAsyncTest.cs | 8 +- .../RestoreImageHealthAsyncTest.cs | 6 +- .../SetEditionAsyncTest.cs | 8 +- src/Microsoft.Dism.Tests/TestWimTemplate.cs | 12 +- .../UnmountImageAsyncTest.cs | 6 +- src/Microsoft.Dism/DismApi.AddCapability.cs | 12 +- src/Microsoft.Dism/DismApi.AddPackage.cs | 8 +- .../DismApi.AddProvisionedAppxPackage.cs | 6 +- .../DismApi.CheckImageHealth.cs | 8 +- src/Microsoft.Dism/DismApi.CommitImage.cs | 8 +- src/Microsoft.Dism/DismApi.DisableFeature.cs | 8 +- src/Microsoft.Dism/DismApi.EnableFeature.cs | 12 +- src/Microsoft.Dism/DismApi.Initialize.cs | 2 +- src/Microsoft.Dism/DismApi.MountImage.cs | 8 +- .../DismApi.RemoveCapability.cs | 8 +- src/Microsoft.Dism/DismApi.RemovePackage.cs | 8 +- .../DismApi.RestoreImageHealth.cs | 12 +- src/Microsoft.Dism/DismApi.SetEdition.cs | 8 +- src/Microsoft.Dism/DismApi.UnmountImage.cs | 8 +- src/Microsoft.Dism/DismUtilities.cs | 4 +- src/Microsoft.Dism/ExtensionMethods.cs | 4 +- stylecop.json | 16 --- 53 files changed, 269 insertions(+), 181 deletions(-) create mode 100644 .editorconfig delete mode 100644 stylecop.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..0cc0bb0 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,113 @@ +root = true + +[*.cs] +csharp_using_directive_placement = outside_namespace:silent +dotnet_sort_system_directives_first = false +dotnet_separate_import_directive_groups = true +file_header_template = Copyright (c). All rights reserved.\n\nLicensed under the MIT license. +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:silent +csharp_style_namespace_declarations = block_scoped:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_prefer_primary_constructors = true:suggestion +csharp_prefer_system_threading_lock = true:suggestion +csharp_style_prefer_simple_property_accessors = true:suggestion +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_style_throw_expression = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:error +csharp_style_prefer_implicitly_typed_lambda_expression = true:suggestion +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_var_for_built_in_types = false:error +csharp_style_var_when_type_is_apparent = false:error +csharp_style_var_elsewhere = false:error +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent +csharp_style_prefer_unbound_generic_type_in_nameof = true:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +[*.{cs,vb}] +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_prefer_collection_expression = when_types_loosely_match:suggestion +dotnet_style_namespace_match_folder = true:suggestion +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +indent_size = 4 +end_of_line = crlf +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent diff --git a/.gitignore b/.gitignore index aeb948b..b49744d 100644 --- a/.gitignore +++ b/.gitignore @@ -24,8 +24,9 @@ bld/ # Visual Studio 2015 cache/options directory .vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ + +# Copilot directory +.copilot # MSTest test Results [Tt]est[Rr]esult*/ diff --git a/Directory.Packages.props b/Directory.Packages.props index aa7a684..9a7b44b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,20 +3,18 @@ true + - - + - - \ No newline at end of file diff --git a/Microsoft.Dism.sln b/Microsoft.Dism.sln index 18534c5..ea3fed3 100644 --- a/Microsoft.Dism.sln +++ b/Microsoft.Dism.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 18 -VisualStudioVersion = 18.3.11214.30 main +VisualStudioVersion = 18.3.11214.30 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Dism", "src\Microsoft.Dism\Microsoft.Dism.csproj", "{E6831090-F1C2-4619-9AB2-01D29272357A}" EndProject @@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Dism.Tests", "src EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2173DC1F-7069-4707-963D-04DCF86C4976}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + .gitignore = .gitignore CONTRIBUTING.md = CONTRIBUTING.md .github\dependabot.yml = .github\dependabot.yml Directory.Build.props = Directory.Build.props @@ -20,7 +22,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution LICENSE = LICENSE NuGet.config = NuGet.config README.md = README.md - stylecop.json = stylecop.json version.json = version.json EndProjectSection EndProject diff --git a/src/Microsoft.Dism.Tests/AddCapabilityAsyncTest.cs b/src/Microsoft.Dism.Tests/AddCapabilityAsyncTest.cs index 4cccd23..7b25e51 100644 --- a/src/Microsoft.Dism.Tests/AddCapabilityAsyncTest.cs +++ b/src/Microsoft.Dism.Tests/AddCapabilityAsyncTest.cs @@ -21,7 +21,7 @@ public AddCapabilityAsyncTest(TestWimTemplate template, ITestOutputHelper testOu public async Task AddCapabilityAsyncCancellation() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -42,9 +42,9 @@ public async Task AddCapabilityAsyncCancellation() public async Task AddCapabilityAsyncWithProgress() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); - var progress = new SynchronousProgress(_ => + SynchronousProgress progress = new(_ => { cts.Cancel(); }); diff --git a/src/Microsoft.Dism.Tests/AddPackageAsyncTest.cs b/src/Microsoft.Dism.Tests/AddPackageAsyncTest.cs index 87bab3c..2ba5849 100644 --- a/src/Microsoft.Dism.Tests/AddPackageAsyncTest.cs +++ b/src/Microsoft.Dism.Tests/AddPackageAsyncTest.cs @@ -21,7 +21,7 @@ public AddPackageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutpu public async Task AddPackageAsyncCancellation() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -42,9 +42,9 @@ public async Task AddPackageAsyncCancellation() public async Task AddPackageAsyncWithProgress() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); - var progress = new SynchronousProgress(_ => + SynchronousProgress progress = new(_ => { cts.Cancel(); }); diff --git a/src/Microsoft.Dism.Tests/ApplyUnattendTest.cs b/src/Microsoft.Dism.Tests/ApplyUnattendTest.cs index 129260f..dd523ce 100644 --- a/src/Microsoft.Dism.Tests/ApplyUnattendTest.cs +++ b/src/Microsoft.Dism.Tests/ApplyUnattendTest.cs @@ -34,7 +34,7 @@ public void ApplyUnattendSimple() "; - FileInfo unattendXmlFile = new FileInfo(Path.Combine(TestDirectory.FullName, "unattend.xml")); + FileInfo unattendXmlFile = new(Path.Combine(TestDirectory.FullName, "unattend.xml")); unattendXmlFile.WriteAllText(unattendXml); diff --git a/src/Microsoft.Dism.Tests/CheckImageHealthAsyncTest.cs b/src/Microsoft.Dism.Tests/CheckImageHealthAsyncTest.cs index f3de6c8..3ab2211 100644 --- a/src/Microsoft.Dism.Tests/CheckImageHealthAsyncTest.cs +++ b/src/Microsoft.Dism.Tests/CheckImageHealthAsyncTest.cs @@ -32,7 +32,7 @@ public async Task CheckImageHealthAsyncOnlineSession() public async Task CheckImageHealthAsyncCancellation() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -56,9 +56,9 @@ public async Task CheckImageHealthAsyncWithProgress() int total = -1; using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); - var progress = new SynchronousProgress(p => + SynchronousProgress progress = new(p => { current = p.Current; total = p.Total; diff --git a/src/Microsoft.Dism.Tests/CommitImageAsyncTest.cs b/src/Microsoft.Dism.Tests/CommitImageAsyncTest.cs index d788c61..9254ba6 100644 --- a/src/Microsoft.Dism.Tests/CommitImageAsyncTest.cs +++ b/src/Microsoft.Dism.Tests/CommitImageAsyncTest.cs @@ -20,7 +20,7 @@ public CommitImageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutp [Fact] public async Task CommitImageAsyncCancellation() { - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -40,9 +40,9 @@ public async Task CommitImageAsyncCancellation() [Fact] public async Task CommitImageAsyncWithProgress() { - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); - var progress = new SynchronousProgress(_ => + SynchronousProgress progress = new(_ => { cts.Cancel(); }); diff --git a/src/Microsoft.Dism.Tests/DisableFeatureAsyncTest.cs b/src/Microsoft.Dism.Tests/DisableFeatureAsyncTest.cs index 1488787..a9131e2 100644 --- a/src/Microsoft.Dism.Tests/DisableFeatureAsyncTest.cs +++ b/src/Microsoft.Dism.Tests/DisableFeatureAsyncTest.cs @@ -21,7 +21,7 @@ public DisableFeatureAsyncTest(TestWimTemplate template, ITestOutputHelper testO public async Task DisableFeatureAsyncCancellation() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -42,9 +42,9 @@ public async Task DisableFeatureAsyncCancellation() public async Task DisableFeatureAsyncWithProgress() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); - var progress = new SynchronousProgress(_ => + SynchronousProgress progress = new(_ => { cts.Cancel(); }); diff --git a/src/Microsoft.Dism.Tests/DismAppxPackageTest.cs b/src/Microsoft.Dism.Tests/DismAppxPackageTest.cs index 5b56dd2..bcfb759 100644 --- a/src/Microsoft.Dism.Tests/DismAppxPackageTest.cs +++ b/src/Microsoft.Dism.Tests/DismAppxPackageTest.cs @@ -11,7 +11,7 @@ namespace Microsoft.Dism.Tests { public class DismAppxPackageCollectionTest : DismCollectionTest { - private static readonly List Items = new List + private static readonly List Items = new() { new DismApi.DismAppxPackage_ { diff --git a/src/Microsoft.Dism.Tests/DismCapabilityInfoTest.cs b/src/Microsoft.Dism.Tests/DismCapabilityInfoTest.cs index 5411aee..49032c3 100644 --- a/src/Microsoft.Dism.Tests/DismCapabilityInfoTest.cs +++ b/src/Microsoft.Dism.Tests/DismCapabilityInfoTest.cs @@ -9,7 +9,7 @@ namespace Microsoft.Dism.Tests { public class DismCapabilityInfoTest : DismStructTest { - private readonly DismApi.DismCapabilityInfo_ _capabilityInfo = new DismApi.DismCapabilityInfo_ + private readonly DismApi.DismCapabilityInfo_ _capabilityInfo = new() { Name = "6CDAF47E-B7D8-4A46-9B83-E13CDA1706A7", DisplayName = "6411A803-B0CB-4570-9BE7-19644412B3C4", @@ -24,20 +24,20 @@ public DismCapabilityInfoTest(TestWimTemplate template) { } - protected override DismCapabilityInfo Item => new DismCapabilityInfo(ItemPtr); + protected override DismCapabilityInfo Item => new(ItemPtr); protected override object Struct => _capabilityInfo; [Fact] public void DownloadAndInstallSizeDoNotOverflow() { - DismApi.DismCapabilityInfo_ dismCapabilityInfo = new DismApi.DismCapabilityInfo_ + DismApi.DismCapabilityInfo_ dismCapabilityInfo = new() { DownloadSize = (uint)int.MaxValue + 1, InstallSize = (uint)int.MaxValue + 10, }; - DismCapabilityInfo capabilityInfo = new DismCapabilityInfo(dismCapabilityInfo); + DismCapabilityInfo capabilityInfo = new(dismCapabilityInfo); capabilityInfo.DownloadSize.ShouldBe((uint)int.MaxValue + 1); capabilityInfo.InstallSize.ShouldBe((uint)int.MaxValue + 10); diff --git a/src/Microsoft.Dism.Tests/DismCapabilityTest.cs b/src/Microsoft.Dism.Tests/DismCapabilityTest.cs index 827ee73..6b5a76f 100644 --- a/src/Microsoft.Dism.Tests/DismCapabilityTest.cs +++ b/src/Microsoft.Dism.Tests/DismCapabilityTest.cs @@ -11,7 +11,7 @@ namespace Microsoft.Dism.Tests { public class DismCapabilityCollectionTest : DismCollectionTest { - private static readonly List Items = new List + private static readonly List Items = new() { new DismApi.DismCapability_ { diff --git a/src/Microsoft.Dism.Tests/DismCollectionTest.cs b/src/Microsoft.Dism.Tests/DismCollectionTest.cs index 5983624..f08a679 100644 --- a/src/Microsoft.Dism.Tests/DismCollectionTest.cs +++ b/src/Microsoft.Dism.Tests/DismCollectionTest.cs @@ -43,7 +43,7 @@ public void CollectionTest() public void CollectionTest_Empty() { TCollection actual = GetActual(IntPtr.Zero); - ReadOnlyCollection expected = new ReadOnlyCollection(new List(0)); + ReadOnlyCollection expected = new(new List(0)); actual.ShouldBe(expected); } diff --git a/src/Microsoft.Dism.Tests/DismCustomPropertyTest.cs b/src/Microsoft.Dism.Tests/DismCustomPropertyTest.cs index f3d3200..59bc42c 100644 --- a/src/Microsoft.Dism.Tests/DismCustomPropertyTest.cs +++ b/src/Microsoft.Dism.Tests/DismCustomPropertyTest.cs @@ -11,7 +11,7 @@ namespace Microsoft.Dism.Tests { public class DismCustomPropertyCollectionTest : DismCollectionTest { - private static readonly List Items = new List + private static readonly List Items = new() { new DismApi.DismCustomProperty_ { diff --git a/src/Microsoft.Dism.Tests/DismDriverPackageTest.cs b/src/Microsoft.Dism.Tests/DismDriverPackageTest.cs index 9094094..2e19416 100644 --- a/src/Microsoft.Dism.Tests/DismDriverPackageTest.cs +++ b/src/Microsoft.Dism.Tests/DismDriverPackageTest.cs @@ -11,7 +11,7 @@ namespace Microsoft.Dism.Tests { public class DismDriverPackageCollectionTest : DismCollectionTest { - private static readonly List Items = new List + private static readonly List Items = new() { new DismApi.DismDriverPackage_ { diff --git a/src/Microsoft.Dism.Tests/DismDriverTest.cs b/src/Microsoft.Dism.Tests/DismDriverTest.cs index aeaeadb..abdd735 100644 --- a/src/Microsoft.Dism.Tests/DismDriverTest.cs +++ b/src/Microsoft.Dism.Tests/DismDriverTest.cs @@ -11,7 +11,7 @@ namespace Microsoft.Dism.Tests { public class DismDriverCollectionTest : DismCollectionTest { - private static readonly List Items = new List + private static readonly List Items = new() { new DismApi.DismDriver_ { diff --git a/src/Microsoft.Dism.Tests/DismFeatureInfoTest.cs b/src/Microsoft.Dism.Tests/DismFeatureInfoTest.cs index 4d97749..b4a6144 100644 --- a/src/Microsoft.Dism.Tests/DismFeatureInfoTest.cs +++ b/src/Microsoft.Dism.Tests/DismFeatureInfoTest.cs @@ -10,18 +10,16 @@ namespace Microsoft.Dism.Tests { public class DismFeatureInfoTest : DismStructTest { - private readonly DismApi.DismFeatureInfo_ _featureInfo = new DismApi.DismFeatureInfo_ + private readonly DismApi.DismFeatureInfo_ _featureInfo = new() { CustomProperty = new List { - new DismApi.DismCustomProperty_ - { + new() { Name = "Property1", Path = "Path1", Value = "Value1", }, - new DismApi.DismCustomProperty_ - { + new() { Name = "Property2", Path = "Path2", Value = "Value2", @@ -40,7 +38,7 @@ public DismFeatureInfoTest(TestWimTemplate template) { } - protected override DismFeatureInfo Item => new DismFeatureInfo(ItemPtr); + protected override DismFeatureInfo Item => new(ItemPtr); protected override object Struct => _featureInfo; diff --git a/src/Microsoft.Dism.Tests/DismFeatureTest.cs b/src/Microsoft.Dism.Tests/DismFeatureTest.cs index c2fc373..263aa48 100644 --- a/src/Microsoft.Dism.Tests/DismFeatureTest.cs +++ b/src/Microsoft.Dism.Tests/DismFeatureTest.cs @@ -11,7 +11,7 @@ namespace Microsoft.Dism.Tests { public class DismFeatureCollectionTest : DismCollectionTest { - private static readonly List Items = new List + private static readonly List Items = new() { new DismApi.DismFeature_ { diff --git a/src/Microsoft.Dism.Tests/DismImageInfoTest.cs b/src/Microsoft.Dism.Tests/DismImageInfoTest.cs index c6a8b70..dc83e5d 100644 --- a/src/Microsoft.Dism.Tests/DismImageInfoTest.cs +++ b/src/Microsoft.Dism.Tests/DismImageInfoTest.cs @@ -12,7 +12,7 @@ namespace Microsoft.Dism.Tests { public class DismImageInfoCollectionTest : DismCollectionTest { - private readonly List _items = new List + private readonly List _items = new() { new DismApi.DismImageInfo_ { @@ -37,8 +37,8 @@ public class DismImageInfoCollectionTest : DismCollectionTest { - new DismApi.DismLanguage("en-us"), - new DismApi.DismLanguage("es-es"), + new("en-us"), + new("es-es"), }.ToPtr(), LanguageCount = 2, MajorVersion = 2, @@ -73,7 +73,7 @@ public class DismImageInfoCollectionTest : DismCollectionTest { - new DismApi.DismLanguage("es-es"), + new("es-es"), }.ToPtr(), LanguageCount = 1, MajorVersion = 2, diff --git a/src/Microsoft.Dism.Tests/DismInitializeTest.cs b/src/Microsoft.Dism.Tests/DismInitializeTest.cs index 464084d..8617128 100644 --- a/src/Microsoft.Dism.Tests/DismInitializeTest.cs +++ b/src/Microsoft.Dism.Tests/DismInitializeTest.cs @@ -56,7 +56,7 @@ public void InitializeExWithLogFilePath() [Fact] public void InitializeExWithScratchDirectory() { - FileInfo logFile = new FileInfo(Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid():N}.log")); + FileInfo logFile = new(Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid():N}.log")); DirectoryInfo scratchDirectory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); DismApi.InitializeEx(DismLogLevel.LogErrors, logFile.FullName, scratchDirectory.FullName); @@ -121,7 +121,7 @@ public void InitializeWithLogFilePath() [Fact] public void InitializeWithScratchDirectory() { - FileInfo logFile = new FileInfo(Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid():N}.log")); + FileInfo logFile = new(Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid():N}.log")); DirectoryInfo scratchDirectory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); DismApi.Initialize(DismLogLevel.LogErrors, logFile.FullName, scratchDirectory.FullName); diff --git a/src/Microsoft.Dism.Tests/DismMountedImageInfoTest.cs b/src/Microsoft.Dism.Tests/DismMountedImageInfoTest.cs index afb0692..41f1387 100644 --- a/src/Microsoft.Dism.Tests/DismMountedImageInfoTest.cs +++ b/src/Microsoft.Dism.Tests/DismMountedImageInfoTest.cs @@ -11,7 +11,7 @@ namespace Microsoft.Dism.Tests { public class DismMountedImageInfoCollectionTest : DismCollectionTest { - private static readonly List Items = new List + private static readonly List Items = new() { new DismApi.DismMountedImageInfo_ { diff --git a/src/Microsoft.Dism.Tests/DismPackageInfoExTest.cs b/src/Microsoft.Dism.Tests/DismPackageInfoExTest.cs index a36b972..8510351 100644 --- a/src/Microsoft.Dism.Tests/DismPackageInfoExTest.cs +++ b/src/Microsoft.Dism.Tests/DismPackageInfoExTest.cs @@ -11,7 +11,7 @@ namespace Microsoft.Dism.Tests { public class DismPackageInfoExTest : DismStructTest { - private readonly DismApi.DismPackageInfoEx_ _packageInfo = new DismApi.DismPackageInfoEx_ + private readonly DismApi.DismPackageInfoEx_ _packageInfo = new() { PackageInfo = new DismApi.DismPackageInfo_ { @@ -21,8 +21,7 @@ public class DismPackageInfoExTest : DismStructTest CreationTime = DateTime.Today.AddDays(-5), CustomProperty = new List { - new DismApi.DismCustomProperty_ - { + new() { Name = "TheName", Path = "ThePath", Value = "TheValue", @@ -33,13 +32,11 @@ public class DismPackageInfoExTest : DismStructTest DisplayName = "DisplayName", Feature = new List { - new DismApi.DismFeature_ - { + new() { FeatureName = "Feature1", State = DismPackageFeatureState.PartiallyInstalled, }, - new DismApi.DismFeature_ - { + new() { FeatureName = "Feature2", State = DismPackageFeatureState.Installed, }, @@ -66,7 +63,7 @@ public DismPackageInfoExTest(TestWimTemplate template) { } - protected override DismPackageInfoEx Item => new DismPackageInfoEx(ItemPtr); + protected override DismPackageInfoEx Item => new(ItemPtr); protected override object Struct => _packageInfo; diff --git a/src/Microsoft.Dism.Tests/DismPackageInfoTest.cs b/src/Microsoft.Dism.Tests/DismPackageInfoTest.cs index 4e01c1e..da1a007 100644 --- a/src/Microsoft.Dism.Tests/DismPackageInfoTest.cs +++ b/src/Microsoft.Dism.Tests/DismPackageInfoTest.cs @@ -11,7 +11,7 @@ namespace Microsoft.Dism.Tests { public class DismPackageInfoTest : DismStructTest { - private readonly DismApi.DismPackageInfo_ _packageInfo = new DismApi.DismPackageInfo_ + private readonly DismApi.DismPackageInfo_ _packageInfo = new() { Applicable = true, Company = "Company", @@ -19,14 +19,12 @@ public class DismPackageInfoTest : DismStructTest CreationTime = DateTime.Today.AddDays(-5), CustomProperty = new List { - new DismApi.DismCustomProperty_ - { + new() { Name = "Name1", Path = "Path1", Value = "Value1", }, - new DismApi.DismCustomProperty_ - { + new() { Name = "Name2", Path = "Path2", Value = "Value2", @@ -37,13 +35,11 @@ public class DismPackageInfoTest : DismStructTest DisplayName = "DisplayName", Feature = new List { - new DismApi.DismFeature_ - { + new() { FeatureName = "FeatureName1", State = DismPackageFeatureState.Installed, }, - new DismApi.DismFeature_ - { + new() { FeatureName = "FeatureName2", State = DismPackageFeatureState.Superseded, }, @@ -68,7 +64,7 @@ public DismPackageInfoTest(TestWimTemplate template) { } - protected override DismPackageInfo Item => new DismPackageInfo(ItemPtr); + protected override DismPackageInfo Item => new(ItemPtr); protected override object Struct => _packageInfo; diff --git a/src/Microsoft.Dism.Tests/DismPackageTest.cs b/src/Microsoft.Dism.Tests/DismPackageTest.cs index fe798ae..dc858d7 100644 --- a/src/Microsoft.Dism.Tests/DismPackageTest.cs +++ b/src/Microsoft.Dism.Tests/DismPackageTest.cs @@ -11,7 +11,7 @@ namespace Microsoft.Dism.Tests { public class DismPackageCollectionTest : DismCollectionTest { - private static readonly List Items = new List + private static readonly List Items = new() { new DismApi.DismPackage_ { diff --git a/src/Microsoft.Dism.Tests/DismSessionTest.cs b/src/Microsoft.Dism.Tests/DismSessionTest.cs index e70ca7f..24f3184 100644 --- a/src/Microsoft.Dism.Tests/DismSessionTest.cs +++ b/src/Microsoft.Dism.Tests/DismSessionTest.cs @@ -18,7 +18,7 @@ public DismSessionTest(TestWimTemplate template, ITestOutputHelper testOutput) [Fact] public void SessionOptionsDefaults() { - DismSessionOptions options = new DismSessionOptions(); + DismSessionOptions options = new(); options.ThrowExceptionOnRebootRequired.ShouldBeTrue(); } diff --git a/src/Microsoft.Dism.Tests/DismWimCustomizedInfoTest.cs b/src/Microsoft.Dism.Tests/DismWimCustomizedInfoTest.cs index 8f48ee5..3dd3a46 100644 --- a/src/Microsoft.Dism.Tests/DismWimCustomizedInfoTest.cs +++ b/src/Microsoft.Dism.Tests/DismWimCustomizedInfoTest.cs @@ -9,7 +9,7 @@ namespace Microsoft.Dism.Tests { public class DismWimCustomizedInfoTest : DismStructTest { - private readonly DismApi.DismWimCustomizedInfo_ _customizedInfo = new DismApi.DismWimCustomizedInfo_ + private readonly DismApi.DismWimCustomizedInfo_ _customizedInfo = new() { CreatedTime = DateTime.Today.AddDays(-15), DirectoryCount = 123, @@ -23,7 +23,7 @@ public DismWimCustomizedInfoTest(TestWimTemplate template) { } - protected override DismWimCustomizedInfo Item => new DismWimCustomizedInfo(_customizedInfo); + protected override DismWimCustomizedInfo Item => new(_customizedInfo); protected override object Struct => _customizedInfo; diff --git a/src/Microsoft.Dism.Tests/EnableFeatureAsyncTest.cs b/src/Microsoft.Dism.Tests/EnableFeatureAsyncTest.cs index 755f369..17ae751 100644 --- a/src/Microsoft.Dism.Tests/EnableFeatureAsyncTest.cs +++ b/src/Microsoft.Dism.Tests/EnableFeatureAsyncTest.cs @@ -21,7 +21,7 @@ public EnableFeatureAsyncTest(TestWimTemplate template, ITestOutputHelper testOu public async Task EnableFeatureAsyncCancellation() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -42,7 +42,7 @@ public async Task EnableFeatureAsyncCancellation() public async Task EnableFeatureByPackageNameAsyncCancellation() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -63,7 +63,7 @@ public async Task EnableFeatureByPackageNameAsyncCancellation() public async Task EnableFeatureByPackagePathAsyncCancellation() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -84,9 +84,9 @@ public async Task EnableFeatureByPackagePathAsyncCancellation() public async Task EnableFeatureAsyncWithProgress() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); - var progress = new SynchronousProgress(_ => + SynchronousProgress progress = new(_ => { cts.Cancel(); }); diff --git a/src/Microsoft.Dism.Tests/ExtensionMethods.cs b/src/Microsoft.Dism.Tests/ExtensionMethods.cs index c679ecd..3de5426 100644 --- a/src/Microsoft.Dism.Tests/ExtensionMethods.cs +++ b/src/Microsoft.Dism.Tests/ExtensionMethods.cs @@ -21,7 +21,7 @@ public static IntPtr ToPtr(this IList list) for (int i = 0; i < list.Count; i++) { - IntPtr currentPtr = new IntPtr(startPtr + (i * structSize)); + IntPtr currentPtr = new(startPtr + (i * structSize)); Marshal.StructureToPtr(list[i] !, currentPtr, false); } diff --git a/src/Microsoft.Dism.Tests/MountImageAsyncTest.cs b/src/Microsoft.Dism.Tests/MountImageAsyncTest.cs index c7ded4e..9e818c9 100644 --- a/src/Microsoft.Dism.Tests/MountImageAsyncTest.cs +++ b/src/Microsoft.Dism.Tests/MountImageAsyncTest.cs @@ -48,7 +48,7 @@ public async Task MountImageAsyncByIndexHappyPath() [Fact] public async Task MountImageAsyncByIndexCancellation() { - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -68,7 +68,7 @@ public async Task MountImageAsyncByIndexCancellation() [Fact] public async Task MountImageAsyncByNameCancellation() { - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -97,9 +97,9 @@ public async Task MountImageAsyncWithProgress() DismApi.CleanupMountpoints(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); - var progress = new SynchronousProgress(_ => + SynchronousProgress progress = new(_ => { progressCalled = true; }); diff --git a/src/Microsoft.Dism.Tests/RemoveCapabilityAsyncTest.cs b/src/Microsoft.Dism.Tests/RemoveCapabilityAsyncTest.cs index 802aab9..fbf955b 100644 --- a/src/Microsoft.Dism.Tests/RemoveCapabilityAsyncTest.cs +++ b/src/Microsoft.Dism.Tests/RemoveCapabilityAsyncTest.cs @@ -21,7 +21,7 @@ public RemoveCapabilityAsyncTest(TestWimTemplate template, ITestOutputHelper tes public async Task RemoveCapabilityAsyncCancellation() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -42,9 +42,9 @@ public async Task RemoveCapabilityAsyncCancellation() public async Task RemoveCapabilityAsyncWithProgress() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); - var progress = new SynchronousProgress(_ => + SynchronousProgress progress = new(_ => { cts.Cancel(); }); diff --git a/src/Microsoft.Dism.Tests/RemovePackageAsyncTest.cs b/src/Microsoft.Dism.Tests/RemovePackageAsyncTest.cs index ec8ec39..e609256 100644 --- a/src/Microsoft.Dism.Tests/RemovePackageAsyncTest.cs +++ b/src/Microsoft.Dism.Tests/RemovePackageAsyncTest.cs @@ -21,7 +21,7 @@ public RemovePackageAsyncTest(TestWimTemplate template, ITestOutputHelper testOu public async Task RemovePackageByNameAsyncCancellation() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -42,7 +42,7 @@ public async Task RemovePackageByNameAsyncCancellation() public async Task RemovePackageByPathAsyncCancellation() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -63,9 +63,9 @@ public async Task RemovePackageByPathAsyncCancellation() public async Task RemovePackageByNameAsyncWithProgress() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); - var progress = new SynchronousProgress(_ => + SynchronousProgress progress = new(_ => { cts.Cancel(); }); diff --git a/src/Microsoft.Dism.Tests/RestoreImageHealthAsyncTest.cs b/src/Microsoft.Dism.Tests/RestoreImageHealthAsyncTest.cs index a2b0c5d..d162b77 100644 --- a/src/Microsoft.Dism.Tests/RestoreImageHealthAsyncTest.cs +++ b/src/Microsoft.Dism.Tests/RestoreImageHealthAsyncTest.cs @@ -21,7 +21,7 @@ public RestoreImageHealthAsyncTest(TestWimTemplate template, ITestOutputHelper t public async Task RestoreImageHealthAsyncCancellation() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -42,9 +42,9 @@ public async Task RestoreImageHealthAsyncCancellation() public async Task RestoreImageHealthAsyncWithProgress() { using DismSession session = DismApi.OpenOnlineSession(); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); - var progress = new SynchronousProgress(_ => + SynchronousProgress progress = new(_ => { cts.Cancel(); }); diff --git a/src/Microsoft.Dism.Tests/SetEditionAsyncTest.cs b/src/Microsoft.Dism.Tests/SetEditionAsyncTest.cs index 85b8391..02989cb 100644 --- a/src/Microsoft.Dism.Tests/SetEditionAsyncTest.cs +++ b/src/Microsoft.Dism.Tests/SetEditionAsyncTest.cs @@ -20,7 +20,7 @@ public SetEditionAsyncTest(TestWimTemplate template, ITestOutputHelper testOutpu [Fact] public async Task SetEditionAsyncCancellation() { - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -40,7 +40,7 @@ public async Task SetEditionAsyncCancellation() [Fact] public async Task SetEditionAndProductKeyAsyncCancellation() { - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -60,9 +60,9 @@ public async Task SetEditionAndProductKeyAsyncCancellation() [Fact] public async Task SetEditionAsyncWithProgress() { - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); - var progress = new SynchronousProgress(_ => + SynchronousProgress progress = new(_ => { cts.Cancel(); }); diff --git a/src/Microsoft.Dism.Tests/TestWimTemplate.cs b/src/Microsoft.Dism.Tests/TestWimTemplate.cs index 88f4bc6..5994188 100644 --- a/src/Microsoft.Dism.Tests/TestWimTemplate.cs +++ b/src/Microsoft.Dism.Tests/TestWimTemplate.cs @@ -26,9 +26,9 @@ public class TestWimTemplate : IDisposable public const string ProductType = "WinNT"; public const int SpLevel = 0; public const string SystemRoot = "WINDOWS"; - public static readonly CultureInfo DefaultLangauge = new CultureInfo("en-US"); - public static readonly CultureInfo Language = new CultureInfo("en-US"); - public static readonly Version ProductVersion = new Version(6, 3, 9600, 16384); + public static readonly CultureInfo DefaultLangauge = new("en-US"); + public static readonly CultureInfo Language = new("en-US"); + public static readonly Version ProductVersion = new(6, 3, 9600, 16384); private const string TestWimTemplateFilename = @"test_template.wim"; @@ -73,7 +73,7 @@ private string CaptureTemplateImage(string capturePath) throw new DirectoryNotFoundException(string.Format(CultureInfo.CurrentCulture, "Could not find part of the path '{0}'", capturePath)); } - XmlDocument xmlDocument = new XmlDocument + XmlDocument xmlDocument = new() { XmlResolver = null, }; @@ -91,8 +91,8 @@ private string CaptureTemplateImage(string capturePath) xml.ShouldNotBeNull(); - using (StringReader stringReader = new StringReader(xml.OuterXml)) - using (XmlTextReader reader = new XmlTextReader(stringReader) + using (StringReader stringReader = new(xml.OuterXml)) + using (XmlTextReader reader = new(stringReader) { DtdProcessing = DtdProcessing.Prohibit, }) diff --git a/src/Microsoft.Dism.Tests/UnmountImageAsyncTest.cs b/src/Microsoft.Dism.Tests/UnmountImageAsyncTest.cs index cca5761..3829b38 100644 --- a/src/Microsoft.Dism.Tests/UnmountImageAsyncTest.cs +++ b/src/Microsoft.Dism.Tests/UnmountImageAsyncTest.cs @@ -20,7 +20,7 @@ public UnmountImageAsyncTest(TestWimTemplate template, ITestOutputHelper testOut [Fact] public async Task UnmountImageAsyncCancellation() { - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); cts.Cancel(); bool canceled = false; @@ -49,9 +49,9 @@ public async Task UnmountImageAsyncWithProgress() DismApi.CleanupMountpoints(); DismApi.MountImage(InstallWimPath.FullName, MountPath.FullName, 1); - using var cts = new CancellationTokenSource(); + using CancellationTokenSource cts = new(); - var progress = new SynchronousProgress(_ => + SynchronousProgress progress = new(_ => { }); diff --git a/src/Microsoft.Dism/DismApi.AddCapability.cs b/src/Microsoft.Dism/DismApi.AddCapability.cs index c5949b5..2d897ec 100644 --- a/src/Microsoft.Dism/DismApi.AddCapability.cs +++ b/src/Microsoft.Dism/DismApi.AddCapability.cs @@ -55,10 +55,10 @@ public static void AddCapability(DismSession session, string capabilityName, boo public static void AddCapability(DismSession session, string capabilityName, bool limitAccess, List? sourcePaths, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) { // Get the list of source paths as an array - string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; + string[] sourcePathsArray = sourcePaths?.ToArray() ?? []; // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); + DismProgress progress = new(progressCallback, userData); int hresult = NativeMethods.DismAddCapability(session, capabilityName, limitAccess, sourcePathsArray, (uint)sourcePathsArray.Length, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); @@ -81,18 +81,18 @@ public static void AddCapability(DismSession session, string capabilityName, boo /// When the operation requires a reboot to complete. public static Task AddCapabilityAsync(DismSession session, string capabilityName, bool limitAccess, List? sourcePaths, IProgress? progress = null, CancellationToken cancellationToken = default) { - var tcs = new TaskCompletionSource(); + TaskCompletionSource tcs = new(); - var ctsRegistration = default(CancellationTokenRegistration); + CancellationTokenRegistration ctsRegistration = default; Task.Factory.StartNew( () => { try { - string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; + string[] sourcePathsArray = sourcePaths?.ToArray() ?? []; - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); diff --git a/src/Microsoft.Dism/DismApi.AddPackage.cs b/src/Microsoft.Dism/DismApi.AddPackage.cs index 5d2f01a..d952236 100644 --- a/src/Microsoft.Dism/DismApi.AddPackage.cs +++ b/src/Microsoft.Dism/DismApi.AddPackage.cs @@ -60,7 +60,7 @@ public static void AddPackage(DismSession session, string packagePath, bool igno public static void AddPackage(DismSession session, string packagePath, bool ignoreCheck, bool preventPending, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) { // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); + DismProgress progress = new(progressCallback, userData); int hresult = NativeMethods.DismAddPackage(session, packagePath, ignoreCheck, preventPending, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); @@ -84,16 +84,16 @@ public static void AddPackage(DismSession session, string packagePath, bool igno /// When the package is not applicable to the specified session. public static Task AddPackageAsync(DismSession session, string packagePath, bool ignoreCheck, bool preventPending, IProgress? progress = null, CancellationToken cancellationToken = default) { - var tcs = new TaskCompletionSource(); + TaskCompletionSource tcs = new(); - var ctsRegistration = default(CancellationTokenRegistration); + CancellationTokenRegistration ctsRegistration = default; Task.Factory.StartNew( () => { try { - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); diff --git a/src/Microsoft.Dism/DismApi.AddProvisionedAppxPackage.cs b/src/Microsoft.Dism/DismApi.AddProvisionedAppxPackage.cs index 25129bc..ecf1321 100644 --- a/src/Microsoft.Dism/DismApi.AddProvisionedAppxPackage.cs +++ b/src/Microsoft.Dism/DismApi.AddProvisionedAppxPackage.cs @@ -72,11 +72,11 @@ public static void AddProvisionedAppxPackage(DismSession session, string appPath int hresult = NativeMethods._DismAddProvisionedAppxPackage( session, appPath, - dependencyPackages?.ToArray() ?? new string[0], + dependencyPackages?.ToArray() ?? [], (uint)(dependencyPackages?.Count ?? 0), - optionalPackages?.ToArray() ?? new string[0], + optionalPackages?.ToArray() ?? [], (uint)(optionalPackages?.Count ?? 0), - licensePaths?.ToArray() ?? new string[0], + licensePaths?.ToArray() ?? [], (uint)(licensePaths?.Count ?? 0), SkipLicense: licensePaths == null || licensePaths.Count == 0, customDataPath, diff --git a/src/Microsoft.Dism/DismApi.CheckImageHealth.cs b/src/Microsoft.Dism/DismApi.CheckImageHealth.cs index 5622326..f1ed48f 100644 --- a/src/Microsoft.Dism/DismApi.CheckImageHealth.cs +++ b/src/Microsoft.Dism/DismApi.CheckImageHealth.cs @@ -51,7 +51,7 @@ public static DismImageHealthState CheckImageHealth(DismSession session, bool sc public static DismImageHealthState CheckImageHealth(DismSession session, bool scanImage, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) { // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); + DismProgress progress = new(progressCallback, userData); int hresult = NativeMethods.DismCheckImageHealth(session, scanImage, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero, out DismImageHealthState imageHealthState); @@ -73,16 +73,16 @@ public static DismImageHealthState CheckImageHealth(DismSession session, bool sc /// When the operation is canceled. public static Task CheckImageHealthAsync(DismSession session, bool scanImage, IProgress? progress = null, CancellationToken cancellationToken = default) { - var tcs = new TaskCompletionSource(); + TaskCompletionSource tcs = new(); - var ctsRegistration = default(CancellationTokenRegistration); + CancellationTokenRegistration ctsRegistration = default; Task.Factory.StartNew( () => { try { - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); diff --git a/src/Microsoft.Dism/DismApi.CommitImage.cs b/src/Microsoft.Dism/DismApi.CommitImage.cs index 0fb6bbc..37d79fa 100644 --- a/src/Microsoft.Dism/DismApi.CommitImage.cs +++ b/src/Microsoft.Dism/DismApi.CommitImage.cs @@ -51,7 +51,7 @@ public static void CommitImage(DismSession session, bool discardChanges, Microso UInt32 flags = discardChanges ? DISM_DISCARD_IMAGE : DISM_COMMIT_IMAGE; // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); + DismProgress progress = new(progressCallback, userData); int hresult = NativeMethods.DismCommitImage(session, flags, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); @@ -71,9 +71,9 @@ public static void CommitImage(DismSession session, bool discardChanges, Microso /// When the operation is canceled. public static Task CommitImageAsync(DismSession session, bool discardChanges, IProgress? progress = null, CancellationToken cancellationToken = default) { - var tcs = new TaskCompletionSource(); + TaskCompletionSource tcs = new(); - var ctsRegistration = default(CancellationTokenRegistration); + CancellationTokenRegistration ctsRegistration = default; Task.Factory.StartNew( () => @@ -82,7 +82,7 @@ public static Task CommitImageAsync(DismSession session, bool discardChanges, IP { UInt32 flags = discardChanges ? DISM_DISCARD_IMAGE : DISM_COMMIT_IMAGE; - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); diff --git a/src/Microsoft.Dism/DismApi.DisableFeature.cs b/src/Microsoft.Dism/DismApi.DisableFeature.cs index bf1f86b..e25a0ce 100644 --- a/src/Microsoft.Dism/DismApi.DisableFeature.cs +++ b/src/Microsoft.Dism/DismApi.DisableFeature.cs @@ -63,7 +63,7 @@ public static void DisableFeature(DismSession session, string featureName, strin public static void DisableFeature(DismSession session, string featureName, string packageName, bool removePayload, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) { // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); + DismProgress progress = new(progressCallback, userData); int hresult = NativeMethods.DismDisableFeature(session, featureName, packageName, removePayload, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); @@ -88,16 +88,16 @@ public static void DisableFeature(DismSession session, string featureName, strin /// When the operation requires a reboot to complete. public static Task DisableFeatureAsync(DismSession session, string featureName, string packageName, bool removePayload, IProgress? progress = null, CancellationToken cancellationToken = default) { - var tcs = new TaskCompletionSource(); + TaskCompletionSource tcs = new(); - var ctsRegistration = default(CancellationTokenRegistration); + CancellationTokenRegistration ctsRegistration = default; Task.Factory.StartNew( () => { try { - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); diff --git a/src/Microsoft.Dism/DismApi.EnableFeature.cs b/src/Microsoft.Dism/DismApi.EnableFeature.cs index d2652e8..bfb9e9b 100644 --- a/src/Microsoft.Dism/DismApi.EnableFeature.cs +++ b/src/Microsoft.Dism/DismApi.EnableFeature.cs @@ -272,18 +272,18 @@ public static Task EnableFeatureByPackagePathAsync(DismSession session, string f /// private static Task EnableFeatureAsync(DismSession session, string featureName, string? identifier, DismPackageIdentifier packageIdentifier, bool limitAccess, bool enableAll, List? sourcePaths, IProgress? progress, CancellationToken cancellationToken) { - var tcs = new TaskCompletionSource(); + TaskCompletionSource tcs = new(); - var ctsRegistration = default(CancellationTokenRegistration); + CancellationTokenRegistration ctsRegistration = default; Task.Factory.StartNew( () => { try { - string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; + string[] sourcePathsArray = sourcePaths?.ToArray() ?? []; - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); @@ -336,10 +336,10 @@ private static Task EnableFeatureAsync(DismSession session, string featureName, private static void EnableFeature(DismSession session, string featureName, string? identifier, DismPackageIdentifier packageIdentifier, bool limitAccess, bool enableAll, List? sourcePaths, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) { // Get the list of source paths as an array - string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; + string[] sourcePathsArray = sourcePaths?.ToArray() ?? []; // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); + DismProgress progress = new(progressCallback, userData); int hresult = NativeMethods.DismEnableFeature( session: session, diff --git a/src/Microsoft.Dism/DismApi.Initialize.cs b/src/Microsoft.Dism/DismApi.Initialize.cs index 942395f..4bea113 100644 --- a/src/Microsoft.Dism/DismApi.Initialize.cs +++ b/src/Microsoft.Dism/DismApi.Initialize.cs @@ -11,7 +11,7 @@ public static partial class DismApi /// /// Used to lock when initializing or shutting down. /// - private static readonly object InitializeShutDownLock = new object(); + private static readonly object InitializeShutDownLock = new(); /// /// Used to keep track if DismApi has been initialized. diff --git a/src/Microsoft.Dism/DismApi.MountImage.cs b/src/Microsoft.Dism/DismApi.MountImage.cs index d11adf4..5504873 100644 --- a/src/Microsoft.Dism/DismApi.MountImage.cs +++ b/src/Microsoft.Dism/DismApi.MountImage.cs @@ -260,9 +260,9 @@ public static Task MountImageAsync(string imageFilePath, string mountPath, strin /// private static Task MountImageAsync(string imageFilePath, string mountPath, int imageIndex, string? imageName, DismImageIdentifier imageIdentifier, bool readOnly, DismMountImageOptions options, IProgress? progress, CancellationToken cancellationToken) { - var tcs = new TaskCompletionSource(); + TaskCompletionSource tcs = new(); - var ctsRegistration = default(CancellationTokenRegistration); + CancellationTokenRegistration ctsRegistration = default; Task.Factory.StartNew( () => @@ -271,7 +271,7 @@ private static Task MountImageAsync(string imageFilePath, string mountPath, int { uint flags = (readOnly ? DISM_MOUNT_READONLY : DISM_MOUNT_READWRITE) | (uint)options; - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); @@ -326,7 +326,7 @@ private static void MountImage(string imageFilePath, string mountPath, int image uint flags = (readOnly ? DISM_MOUNT_READONLY : DISM_MOUNT_READWRITE) | (uint)options; // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); + DismProgress progress = new(progressCallback, userData); int hresult = NativeMethods.DismMountImage(imageFilePath, mountPath, (uint)imageIndex, imageName, imageIdentifier, flags, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); diff --git a/src/Microsoft.Dism/DismApi.RemoveCapability.cs b/src/Microsoft.Dism/DismApi.RemoveCapability.cs index 731e059..ae97d4c 100644 --- a/src/Microsoft.Dism/DismApi.RemoveCapability.cs +++ b/src/Microsoft.Dism/DismApi.RemoveCapability.cs @@ -37,7 +37,7 @@ public static void RemoveCapability(DismSession session, string capabilityName) public static void RemoveCapability(DismSession session, string capabilityName, Dism.DismProgressCallback? progressCallback, object? userData) { // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); + DismProgress progress = new(progressCallback, userData); int hresult = NativeMethods.DismRemoveCapability(session, capabilityName, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); @@ -58,16 +58,16 @@ public static void RemoveCapability(DismSession session, string capabilityName, /// When the operation requires a reboot to complete. public static Task RemoveCapabilityAsync(DismSession session, string capabilityName, IProgress? progress = null, CancellationToken cancellationToken = default) { - var tcs = new TaskCompletionSource(); + TaskCompletionSource tcs = new(); - var ctsRegistration = default(CancellationTokenRegistration); + CancellationTokenRegistration ctsRegistration = default; Task.Factory.StartNew( () => { try { - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); diff --git a/src/Microsoft.Dism/DismApi.RemovePackage.cs b/src/Microsoft.Dism/DismApi.RemovePackage.cs index fa998c9..6f71699 100644 --- a/src/Microsoft.Dism/DismApi.RemovePackage.cs +++ b/src/Microsoft.Dism/DismApi.RemovePackage.cs @@ -132,16 +132,16 @@ public static Task RemovePackageByPathAsync(DismSession session, string packageP /// private static Task RemovePackageAsync(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, IProgress? progress, CancellationToken cancellationToken) { - var tcs = new TaskCompletionSource(); + TaskCompletionSource tcs = new(); - var ctsRegistration = default(CancellationTokenRegistration); + CancellationTokenRegistration ctsRegistration = default; Task.Factory.StartNew( () => { try { - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); @@ -189,7 +189,7 @@ private static Task RemovePackageAsync(DismSession session, string identifier, D private static void RemovePackage(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, Dism.DismProgressCallback? progressCallback, object? userData) { // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); + DismProgress progress = new(progressCallback, userData); int hresult = NativeMethods.DismRemovePackage(session, identifier, packageIdentifier, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); diff --git a/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs b/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs index e7501ae..7f350fa 100644 --- a/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs +++ b/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs @@ -67,10 +67,10 @@ public static void RestoreImageHealth(DismSession session, bool limitAccess, Lis public static void RestoreImageHealth(DismSession session, bool limitAccess, List? sourcePaths, Dism.DismProgressCallback? progressCallback, object? userData) { // Get the list of source paths as an array - string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; + string[] sourcePathsArray = sourcePaths?.ToArray() ?? []; // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); + DismProgress progress = new(progressCallback, userData); int hresult = NativeMethods.DismRestoreImageHealth(session, sourcePathsArray, (uint)sourcePathsArray.Length, limitAccess, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); @@ -92,18 +92,18 @@ public static void RestoreImageHealth(DismSession session, bool limitAccess, Lis /// When the operation requires a reboot to complete. public static Task RestoreImageHealthAsync(DismSession session, bool limitAccess, List? sourcePaths = null, IProgress? progress = null, CancellationToken cancellationToken = default) { - var tcs = new TaskCompletionSource(); + TaskCompletionSource tcs = new(); - var ctsRegistration = default(CancellationTokenRegistration); + CancellationTokenRegistration ctsRegistration = default; Task.Factory.StartNew( () => { try { - string[] sourcePathsArray = sourcePaths?.ToArray() ?? new string[0]; + string[] sourcePathsArray = sourcePaths?.ToArray() ?? []; - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); diff --git a/src/Microsoft.Dism/DismApi.SetEdition.cs b/src/Microsoft.Dism/DismApi.SetEdition.cs index e60d09c..b8d73f8 100644 --- a/src/Microsoft.Dism/DismApi.SetEdition.cs +++ b/src/Microsoft.Dism/DismApi.SetEdition.cs @@ -132,16 +132,16 @@ public static Task SetEditionAndProductKeyAsync(DismSession session, string edit /// private static Task SetEditionAsync(DismSession session, string editionId, string? productKey, IProgress? progress, CancellationToken cancellationToken) { - var tcs = new TaskCompletionSource(); + TaskCompletionSource tcs = new(); - var ctsRegistration = default(CancellationTokenRegistration); + CancellationTokenRegistration ctsRegistration = default; Task.Factory.StartNew( () => { try { - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); @@ -191,7 +191,7 @@ private static Task SetEditionAsync(DismSession session, string editionId, strin private static void SetEdition(DismSession session, string editionId, string? productKey, Dism.DismProgressCallback? progressCallback, object? userData) { // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); + DismProgress progress = new(progressCallback, userData); int hresult = NativeMethods.DismSetEdition(session, editionId, productKey, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); diff --git a/src/Microsoft.Dism/DismApi.UnmountImage.cs b/src/Microsoft.Dism/DismApi.UnmountImage.cs index 2a86b41..7331b5d 100644 --- a/src/Microsoft.Dism/DismApi.UnmountImage.cs +++ b/src/Microsoft.Dism/DismApi.UnmountImage.cs @@ -51,7 +51,7 @@ public static void UnmountImage(string mountPath, bool commitChanges, Dism.DismP uint flags = commitChanges ? DISM_COMMIT_IMAGE : DISM_DISCARD_IMAGE; // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new DismProgress(progressCallback, userData); + DismProgress progress = new(progressCallback, userData); int hresult = NativeMethods.DismUnmountImage(mountPath, flags, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); @@ -71,9 +71,9 @@ public static void UnmountImage(string mountPath, bool commitChanges, Dism.DismP /// When the operation is canceled. public static Task UnmountImageAsync(string mountPath, bool commitChanges, IProgress? progress = null, CancellationToken cancellationToken = default) { - var tcs = new TaskCompletionSource(); + TaskCompletionSource tcs = new(); - var ctsRegistration = default(CancellationTokenRegistration); + CancellationTokenRegistration ctsRegistration = default; Task.Factory.StartNew( () => @@ -82,7 +82,7 @@ public static Task UnmountImageAsync(string mountPath, bool commitChanges, IProg { uint flags = commitChanges ? DISM_COMMIT_IMAGE : DISM_DISCARD_IMAGE; - var dismProgress = new DismProgress(progress != null ? p => progress.Report(p) : null, null); + DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); diff --git a/src/Microsoft.Dism/DismUtilities.cs b/src/Microsoft.Dism/DismUtilities.cs index 6608c5c..29bbd4d 100644 --- a/src/Microsoft.Dism/DismUtilities.cs +++ b/src/Microsoft.Dism/DismUtilities.cs @@ -147,7 +147,7 @@ public static string? WAIKDISMAPIPath return null; } - FileInfo dismPath = new FileInfo(Path.Combine(servicingPath, "dism.exe")); + FileInfo dismPath = new(Path.Combine(servicingPath, "dism.exe")); return dismPath.Exists ? dismPath.FullName : null; } @@ -290,7 +290,7 @@ internal static void ThrowIfFail(int hresult, DismSession? session = null, [Call return null; } - FileInfo dismPath = new FileInfo(Path.Combine(kitsRoot, "Assessment and Deployment Kit", "Deployment Tools", Environment.Is64BitProcess ? "amd64" : "x86", "DISM", "dismapi.dll")); + FileInfo dismPath = new(Path.Combine(kitsRoot, "Assessment and Deployment Kit", "Deployment Tools", Environment.Is64BitProcess ? "amd64" : "x86", "DISM", "dismapi.dll")); return dismPath.Exists ? dismPath.FullName : null; } diff --git a/src/Microsoft.Dism/ExtensionMethods.cs b/src/Microsoft.Dism/ExtensionMethods.cs index 381ca23..6933e18 100644 --- a/src/Microsoft.Dism/ExtensionMethods.cs +++ b/src/Microsoft.Dism/ExtensionMethods.cs @@ -33,7 +33,7 @@ public static List ToList(this IntPtr ptr, uint count, Func list = new List((int)count); + List list = new((int)count); if (ptr != IntPtr.Zero && count > 0) { @@ -48,7 +48,7 @@ public static List ToList(this IntPtr ptr, uint count, Func(); diff --git a/stylecop.json b/stylecop.json deleted file mode 100644 index 3e69aeb..0000000 --- a/stylecop.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", - "settings": { - "orderingRules": { - "usingDirectivesPlacement": "outsideNamespace", - "systemUsingDirectivesFirst": false, - "blankLinesBetweenUsingGroups": "require", - - }, - "documentationRules": { - "companyName": "", - "copyrightText": "Copyright (c). All rights reserved.\n\nLicensed under the MIT license.", - "xmlHeader": false - } - } -} \ No newline at end of file From 2c2c360394f047122ff4a1499d4efe105ebf379e Mon Sep 17 00:00:00 2001 From: Jeff Kluge Date: Tue, 14 Apr 2026 17:37:40 -0700 Subject: [PATCH 13/13] step --- .editorconfig | 6 +- Directory.Build.targets | 2 +- .../AddCapabilityAsyncTest.cs | 83 ---- .../AddPackageAsyncTest.cs | 83 ---- .../CheckImageHealthAsyncTest.cs | 98 ----- .../CheckImageHealthTest.cs | 67 ++- .../CommitImageAsyncTest.cs | 83 ---- .../DisableFeatureAsyncTest.cs | 83 ---- .../EnableFeatureAsyncTest.cs | 125 ------ .../GetCurrentEditionTests.cs | 2 +- .../Microsoft.Dism.Tests.csproj | 2 +- .../MountImageAsyncTest.cs | 142 ------- src/Microsoft.Dism.Tests/MountImageTest.cs | 92 +++++ .../RemoveCapabilityAsyncTest.cs | 83 ---- .../RemovePackageAsyncTest.cs | 104 ----- .../RestoreImageHealthAsyncTest.cs | 79 ---- .../SetEditionAsyncTest.cs | 101 ----- src/Microsoft.Dism.Tests/TestWimTemplate.cs | 4 +- .../UnmountImageAsyncTest.cs | 109 ----- .../CallerMemberNameAttribute.cs | 16 - src/Microsoft.Dism/DismApi.AddCapability.cs | 132 +++--- src/Microsoft.Dism/DismApi.AddDriver.cs | 14 +- src/Microsoft.Dism/DismApi.AddPackage.cs | 130 +++--- .../DismApi.AddProvisionedAppxPackage.cs | 29 +- src/Microsoft.Dism/DismApi.ApplyFfuImage.cs | 12 +- src/Microsoft.Dism/DismApi.ApplyUnattend.cs | 12 +- .../DismApi.CheckImageHealth.cs | 122 +++--- .../DismApi.CleanupMountpoints.cs | 9 +- src/Microsoft.Dism/DismApi.CloseSession.cs | 10 +- src/Microsoft.Dism/DismApi.CommitImage.cs | 136 +++--- src/Microsoft.Dism/DismApi.Delete.cs | 10 +- src/Microsoft.Dism/DismApi.DisableFeature.cs | 166 +++++--- src/Microsoft.Dism/DismApi.EnableFeature.cs | 387 ++++++++++++------ src/Microsoft.Dism/DismApi.GetCapabilities.cs | 12 +- .../DismApi.GetCapabilityInfo.cs | 12 +- .../DismApi.GetCurrentEdition.cs | 11 +- src/Microsoft.Dism/DismApi.GetDriverInfo.cs | 14 +- src/Microsoft.Dism/DismApi.GetDrivers.cs | 15 +- src/Microsoft.Dism/DismApi.GetFeatureInfo.cs | 14 +- .../DismApi.GetFeatureParent.cs | 15 +- src/Microsoft.Dism/DismApi.GetFeatures.cs | 14 +- src/Microsoft.Dism/DismApi.GetImageInfo.cs | 12 +- .../DismApi.GetLastErrorMessage.cs | 10 +- .../DismApi.GetMountedImages.cs | 11 +- src/Microsoft.Dism/DismApi.GetPackageInfo.cs | 13 +- .../DismApi.GetPackageInfoEx.cs | 13 +- src/Microsoft.Dism/DismApi.GetPackages.cs | 12 +- .../DismApi.GetProductKeyInfo.cs | 13 +- .../DismApi.GetProvisionedAppxPackages.cs | 12 +- .../DismApi.GetRegistryMountPoint.cs | 12 +- .../DismApi.GetTargetEditions.cs | 12 +- src/Microsoft.Dism/DismApi.Initialize.cs | 12 +- src/Microsoft.Dism/DismApi.MountImage.cs | 248 +++++++---- src/Microsoft.Dism/DismApi.OpenSession.cs | 13 +- src/Microsoft.Dism/DismApi.RemountImage.cs | 10 +- .../DismApi.RemoveCapability.cs | 135 +++--- src/Microsoft.Dism/DismApi.RemovePackage.cs | 175 +++++--- .../DismApi.RemoveProvisionedAppxPackage.cs | 11 +- .../DismApi.RestoreImageHealth.cs | 144 ++++--- src/Microsoft.Dism/DismApi.SetEdition.cs | 175 ++++---- src/Microsoft.Dism/DismApi.SetProductKey.cs | 11 +- src/Microsoft.Dism/DismApi.SplitFfuImage.cs | 12 +- src/Microsoft.Dism/DismApi.UnmountImage.cs | 126 +++--- .../DismApi.ValidateProductKey.cs | 11 +- src/Microsoft.Dism/DismCustomProperty.cs | 2 +- src/Microsoft.Dism/DismProgress.cs | 10 + src/Microsoft.Dism/DismProgressCallback.cs | 2 +- src/Microsoft.Dism/DismUtilities.cs | 39 ++ src/Microsoft.Dism/GlobalSuppressions.cs | 61 ++- src/Microsoft.Dism/Microsoft.Dism.csproj | 4 +- src/Microsoft.Dism/PublicAPI.Unshipped.txt | 75 +++- src/Microsoft.Dism/SystemTime.cs | 4 +- 72 files changed, 1841 insertions(+), 2199 deletions(-) delete mode 100644 src/Microsoft.Dism.Tests/AddCapabilityAsyncTest.cs delete mode 100644 src/Microsoft.Dism.Tests/AddPackageAsyncTest.cs delete mode 100644 src/Microsoft.Dism.Tests/CheckImageHealthAsyncTest.cs delete mode 100644 src/Microsoft.Dism.Tests/CommitImageAsyncTest.cs delete mode 100644 src/Microsoft.Dism.Tests/DisableFeatureAsyncTest.cs delete mode 100644 src/Microsoft.Dism.Tests/EnableFeatureAsyncTest.cs delete mode 100644 src/Microsoft.Dism.Tests/MountImageAsyncTest.cs create mode 100644 src/Microsoft.Dism.Tests/MountImageTest.cs delete mode 100644 src/Microsoft.Dism.Tests/RemoveCapabilityAsyncTest.cs delete mode 100644 src/Microsoft.Dism.Tests/RemovePackageAsyncTest.cs delete mode 100644 src/Microsoft.Dism.Tests/RestoreImageHealthAsyncTest.cs delete mode 100644 src/Microsoft.Dism.Tests/SetEditionAsyncTest.cs delete mode 100644 src/Microsoft.Dism.Tests/UnmountImageAsyncTest.cs delete mode 100644 src/Microsoft.Dism/CallerMemberNameAttribute.cs diff --git a/.editorconfig b/.editorconfig index 0cc0bb0..47bb059 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,11 +1,11 @@ root = true [*.cs] -csharp_using_directive_placement = outside_namespace:silent +csharp_using_directive_placement = outside_namespace:error dotnet_sort_system_directives_first = false -dotnet_separate_import_directive_groups = true +dotnet_separate_import_directive_groups = false file_header_template = Copyright (c). All rights reserved.\n\nLicensed under the MIT license. -csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_simple_using_statement = true:error csharp_prefer_braces = true:silent csharp_style_namespace_declarations = block_scoped:silent csharp_style_prefer_method_group_conversion = true:silent diff --git a/Directory.Build.targets b/Directory.Build.targets index 76a4afd..47169ae 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -9,7 +9,7 @@ Git true - Full + Full true All Low diff --git a/src/Microsoft.Dism.Tests/AddCapabilityAsyncTest.cs b/src/Microsoft.Dism.Tests/AddCapabilityAsyncTest.cs deleted file mode 100644 index 7b25e51..0000000 --- a/src/Microsoft.Dism.Tests/AddCapabilityAsyncTest.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c). All rights reserved. -// -// Licensed under the MIT license. -#if !NETFRAMEWORK -using Shouldly; -using System; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Dism.Tests -{ - public class AddCapabilityAsyncTest : DismTestBase - { - public AddCapabilityAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) - : base(template, testOutput) - { - } - - [Fact] - public async Task AddCapabilityAsyncCancellation() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.AddCapabilityAsync(session, "FakeCapability", limitAccess: true, sourcePaths: null, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task AddCapabilityAsyncWithProgress() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - - SynchronousProgress progress = new(_ => - { - cts.Cancel(); - }); - - try - { - await DismApi.AddCapabilityAsync(session, "FakeCapability", limitAccess: true, sourcePaths: null, progress: progress, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - } - catch (DismException) - { - // Expected when the capability does not exist - } - - // Progress may not be called for an invalid capability, so we just verify no hang occurred - } - - private sealed class SynchronousProgress : IProgress - { - private readonly Action _handler; - - public SynchronousProgress(Action handler) - { - _handler = handler; - } - - public void Report(T value) - { - _handler(value); - } - } - } -} -#endif diff --git a/src/Microsoft.Dism.Tests/AddPackageAsyncTest.cs b/src/Microsoft.Dism.Tests/AddPackageAsyncTest.cs deleted file mode 100644 index 2ba5849..0000000 --- a/src/Microsoft.Dism.Tests/AddPackageAsyncTest.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c). All rights reserved. -// -// Licensed under the MIT license. -#if !NETFRAMEWORK -using Shouldly; -using System; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Dism.Tests -{ - public class AddPackageAsyncTest : DismTestBase - { - public AddPackageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) - : base(template, testOutput) - { - } - - [Fact] - public async Task AddPackageAsyncCancellation() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.AddPackageAsync(session, "nonexistent.cab", ignoreCheck: false, preventPending: false, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task AddPackageAsyncWithProgress() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - - SynchronousProgress progress = new(_ => - { - cts.Cancel(); - }); - - try - { - await DismApi.AddPackageAsync(session, "nonexistent.cab", ignoreCheck: false, preventPending: false, progress: progress, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - } - catch (DismException) - { - // Expected when the package does not exist - } - - // Progress may not be called for an invalid package, so we just verify no hang occurred - } - - private sealed class SynchronousProgress : IProgress - { - private readonly Action _handler; - - public SynchronousProgress(Action handler) - { - _handler = handler; - } - - public void Report(T value) - { - _handler(value); - } - } - } -} -#endif diff --git a/src/Microsoft.Dism.Tests/CheckImageHealthAsyncTest.cs b/src/Microsoft.Dism.Tests/CheckImageHealthAsyncTest.cs deleted file mode 100644 index 3ab2211..0000000 --- a/src/Microsoft.Dism.Tests/CheckImageHealthAsyncTest.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c). All rights reserved. -// -// Licensed under the MIT license. - -#if !NETFRAMEWORK -using Shouldly; -using System; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Dism.Tests -{ - public class CheckImageHealthAsyncTest : DismTestBase - { - public CheckImageHealthAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) - : base(template, testOutput) - { - } - - [Fact] - public async Task CheckImageHealthAsyncOnlineSession() - { - using DismSession session = DismApi.OpenOnlineSession(); - - DismImageHealthState imageHealthState = await DismApi.CheckImageHealthAsync(session, scanImage: false, cancellationToken: TestContext.Current.CancellationToken); - - imageHealthState.ShouldBe(DismImageHealthState.Healthy); - } - - [Fact] - public async Task CheckImageHealthAsyncCancellation() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.CheckImageHealthAsync(session, scanImage: false, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task CheckImageHealthAsyncWithProgress() - { - int current = -1; - int total = -1; - - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - - SynchronousProgress progress = new(p => - { - current = p.Current; - total = p.Total; - - // Cancel the operation, otherwise it takes ~1 min - cts.Cancel(); - }); - - try - { - await DismApi.CheckImageHealthAsync(session, scanImage: true, progress: progress, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - } - - current.ShouldBe(50); - total.ShouldBeGreaterThanOrEqualTo(1000); - } - - private sealed class SynchronousProgress : IProgress - { - private readonly Action _handler; - - public SynchronousProgress(Action handler) - { - _handler = handler; - } - - public void Report(T value) - { - _handler(value); - } - } - } -} -#endif diff --git a/src/Microsoft.Dism.Tests/CheckImageHealthTest.cs b/src/Microsoft.Dism.Tests/CheckImageHealthTest.cs index 487fdfb..5c5333f 100644 --- a/src/Microsoft.Dism.Tests/CheckImageHealthTest.cs +++ b/src/Microsoft.Dism.Tests/CheckImageHealthTest.cs @@ -3,7 +3,11 @@ // Licensed under the MIT license. using Shouldly; + using System; +using System.Threading; +using System.Threading.Tasks; + using Xunit; namespace Microsoft.Dism.Tests @@ -15,6 +19,67 @@ public CheckImageHealthTest(TestWimTemplate template, ITestOutputHelper testOutp { } + [Fact] + public async Task CheckImageHealthAsyncCancellation() + { + using DismSession session = DismApi.OpenOnlineSession(); + using CancellationTokenSource cts = new(); + + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.CheckImageHealthAsync(session, scanImage: false, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task CheckImageHealthAsyncOnlineSession() + { + using DismSession session = DismApi.OpenOnlineSession(); + + DismImageHealthState imageHealthState = await DismApi.CheckImageHealthAsync(session, scanImage: false, cancellationToken: TestContext.Current.CancellationToken); + + imageHealthState.ShouldBe(DismImageHealthState.Healthy); + } + + [Fact] + public async Task CheckImageHealthAsyncWithProgress() + { + int current = -1; + int total = -1; + + using DismSession session = DismApi.OpenOnlineSession(); + using CancellationTokenSource cts = new(); + + Progress progress = new(dismProgress => + { + current = dismProgress.Current; + total = dismProgress.Total; + + dismProgress.Cancel = true; // Cancel the operation, otherwise it takes a few minutes + }); + + try + { + await DismApi.CheckImageHealthAsync(session, scanImage: true, progress: progress, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + } + + current.ShouldBeGreaterThan(-1); + total.ShouldBeGreaterThan(-1); + } + [Fact] public void CheckImageHealthOnlineSession() { @@ -60,4 +125,4 @@ public void CheckImageHealthOnlineSessionWithCallback() total.ShouldBeGreaterThanOrEqualTo(1000); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Dism.Tests/CommitImageAsyncTest.cs b/src/Microsoft.Dism.Tests/CommitImageAsyncTest.cs deleted file mode 100644 index 9254ba6..0000000 --- a/src/Microsoft.Dism.Tests/CommitImageAsyncTest.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c). All rights reserved. -// -// Licensed under the MIT license. -#if !NETFRAMEWORK -using Shouldly; -using System; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Dism.Tests -{ - public class CommitImageAsyncTest : DismInstallWimTestBase - { - public CommitImageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) - : base(template, testOutput) - { - } - - [Fact] - public async Task CommitImageAsyncCancellation() - { - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.CommitImageAsync(Session, discardChanges: true, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task CommitImageAsyncWithProgress() - { - using CancellationTokenSource cts = new(); - - SynchronousProgress progress = new(_ => - { - cts.Cancel(); - }); - - try - { - await DismApi.CommitImageAsync(Session, discardChanges: true, progress: progress, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - } - - // Progress may or may not be called depending on whether changes exist to commit - } - - [Fact] - public async Task CommitImageAsyncHappyPath() - { - await DismApi.CommitImageAsync(Session, discardChanges: true, cancellationToken: TestContext.Current.CancellationToken); - } - - private sealed class SynchronousProgress : IProgress - { - private readonly Action _handler; - - public SynchronousProgress(Action handler) - { - _handler = handler; - } - - public void Report(T value) - { - _handler(value); - } - } - } -} -#endif diff --git a/src/Microsoft.Dism.Tests/DisableFeatureAsyncTest.cs b/src/Microsoft.Dism.Tests/DisableFeatureAsyncTest.cs deleted file mode 100644 index a9131e2..0000000 --- a/src/Microsoft.Dism.Tests/DisableFeatureAsyncTest.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c). All rights reserved. -// -// Licensed under the MIT license. -#if !NETFRAMEWORK -using Shouldly; -using System; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Dism.Tests -{ - public class DisableFeatureAsyncTest : DismTestBase - { - public DisableFeatureAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) - : base(template, testOutput) - { - } - - [Fact] - public async Task DisableFeatureAsyncCancellation() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.DisableFeatureAsync(session, "FakeFeature", packageName: string.Empty, removePayload: false, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task DisableFeatureAsyncWithProgress() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - - SynchronousProgress progress = new(_ => - { - cts.Cancel(); - }); - - try - { - await DismApi.DisableFeatureAsync(session, "FakeFeature", packageName: string.Empty, removePayload: false, progress: progress, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - } - catch (DismException) - { - // Expected when the feature does not exist - } - - // Progress may not be called for an invalid feature, so we just verify no hang occurred - } - - private sealed class SynchronousProgress : IProgress - { - private readonly Action _handler; - - public SynchronousProgress(Action handler) - { - _handler = handler; - } - - public void Report(T value) - { - _handler(value); - } - } - } -} -#endif diff --git a/src/Microsoft.Dism.Tests/EnableFeatureAsyncTest.cs b/src/Microsoft.Dism.Tests/EnableFeatureAsyncTest.cs deleted file mode 100644 index 17ae751..0000000 --- a/src/Microsoft.Dism.Tests/EnableFeatureAsyncTest.cs +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c). All rights reserved. -// -// Licensed under the MIT license. -#if !NETFRAMEWORK -using Shouldly; -using System; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Dism.Tests -{ - public class EnableFeatureAsyncTest : DismTestBase - { - public EnableFeatureAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) - : base(template, testOutput) - { - } - - [Fact] - public async Task EnableFeatureAsyncCancellation() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.EnableFeatureAsync(session, "FakeFeature", limitAccess: true, enableAll: false, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task EnableFeatureByPackageNameAsyncCancellation() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.EnableFeatureByPackageNameAsync(session, "FakeFeature", "FakePackage", limitAccess: true, enableAll: false, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task EnableFeatureByPackagePathAsyncCancellation() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.EnableFeatureByPackagePathAsync(session, "FakeFeature", "FakePackage.cab", limitAccess: true, enableAll: false, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task EnableFeatureAsyncWithProgress() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - - SynchronousProgress progress = new(_ => - { - cts.Cancel(); - }); - - try - { - await DismApi.EnableFeatureAsync(session, "FakeFeature", limitAccess: true, enableAll: false, progress: progress, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - } - catch (DismException) - { - // Expected when the feature does not exist - } - - // Progress may not be called for an invalid feature, so we just verify no hang occurred - } - - private sealed class SynchronousProgress : IProgress - { - private readonly Action _handler; - - public SynchronousProgress(Action handler) - { - _handler = handler; - } - - public void Report(T value) - { - _handler(value); - } - } - } -} -#endif diff --git a/src/Microsoft.Dism.Tests/GetCurrentEditionTests.cs b/src/Microsoft.Dism.Tests/GetCurrentEditionTests.cs index bb63b6b..51acd86 100644 --- a/src/Microsoft.Dism.Tests/GetCurrentEditionTests.cs +++ b/src/Microsoft.Dism.Tests/GetCurrentEditionTests.cs @@ -7,7 +7,7 @@ namespace Microsoft.Dism.Tests { - public class GetCurrentEditionTests : DismInstallWimTestBase + public class GetCurrentEditionTests : DismTestBase { public GetCurrentEditionTests(TestWimTemplate template, ITestOutputHelper testOutput) : base(template, testOutput) diff --git a/src/Microsoft.Dism.Tests/Microsoft.Dism.Tests.csproj b/src/Microsoft.Dism.Tests/Microsoft.Dism.Tests.csproj index 7ddc9d0..6f9c8de 100644 --- a/src/Microsoft.Dism.Tests/Microsoft.Dism.Tests.csproj +++ b/src/Microsoft.Dism.Tests/Microsoft.Dism.Tests.csproj @@ -1,7 +1,7 @@  Exe - net472;net10.0 + net472;net8.0;net10.0 x64 $(NoWarn);SA0001;SA1600;RS0016 diff --git a/src/Microsoft.Dism.Tests/MountImageAsyncTest.cs b/src/Microsoft.Dism.Tests/MountImageAsyncTest.cs deleted file mode 100644 index 9e818c9..0000000 --- a/src/Microsoft.Dism.Tests/MountImageAsyncTest.cs +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c). All rights reserved. -// -// Licensed under the MIT license. - -#if !NETFRAMEWORK -using Shouldly; -using System; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Dism.Tests -{ - public class MountImageAsyncTest : DismTestBase - { - public MountImageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) - : base(template, testOutput) - { - } - - [Fact] - public async Task MountImageAsyncByIndexHappyPath() - { - foreach (DismMountedImageInfo mountedImageInfo in DismApi.GetMountedImages()) - { - DismApi.UnmountImage(mountedImageInfo.MountPath, false); - } - - DismApi.CleanupMountpoints(); - - try - { - await DismApi.MountImageAsync(InstallWimPath.FullName, MountPath.FullName, imageIndex: 1, readOnly: true, options: DismMountImageOptions.None, progress: null, cancellationToken: CancellationToken.None); - } - finally - { - try - { - DismApi.UnmountImage(MountPath.FullName, commitChanges: false); - } - catch - { - // Best effort cleanup - } - } - } - - [Fact] - public async Task MountImageAsyncByIndexCancellation() - { - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.MountImageAsync(InstallWimPath.FullName, MountPath.FullName, imageIndex: 1, readOnly: true, options: DismMountImageOptions.None, progress: null, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task MountImageAsyncByNameCancellation() - { - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.MountImageAsync(InstallWimPath.FullName, MountPath.FullName, imageName: "FakeImage", readOnly: true, options: DismMountImageOptions.None, progress: null, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task MountImageAsyncWithProgress() - { - bool progressCalled = false; - - foreach (DismMountedImageInfo mountedImageInfo in DismApi.GetMountedImages()) - { - DismApi.UnmountImage(mountedImageInfo.MountPath, false); - } - - DismApi.CleanupMountpoints(); - - using CancellationTokenSource cts = new(); - - SynchronousProgress progress = new(_ => - { - progressCalled = true; - }); - - try - { - await DismApi.MountImageAsync(InstallWimPath.FullName, MountPath.FullName, imageIndex: 1, readOnly: true, options: DismMountImageOptions.None, progress: progress, cancellationToken: cts.Token); - } - finally - { - try - { - DismApi.UnmountImage(MountPath.FullName, commitChanges: false); - } - catch - { - // Best effort cleanup - } - } - - progressCalled.ShouldBeTrue(); - } - - private sealed class SynchronousProgress : IProgress - { - private readonly Action _handler; - - public SynchronousProgress(Action handler) - { - _handler = handler; - } - - public void Report(T value) - { - _handler(value); - } - } - } -} -#endif diff --git a/src/Microsoft.Dism.Tests/MountImageTest.cs b/src/Microsoft.Dism.Tests/MountImageTest.cs new file mode 100644 index 0000000..066a1e0 --- /dev/null +++ b/src/Microsoft.Dism.Tests/MountImageTest.cs @@ -0,0 +1,92 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class MountImageTest : DismTestBase + { + public MountImageTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task MountImageAsyncByIndexWithCancellation() + { + using CancellationTokenSource cts = new(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.MountImageAsync(InstallWimPath.FullName, MountPath.FullName, imageIndex: 1, readOnly: true, options: DismMountImageOptions.None, progress: null, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task MountImageAsyncByNameWithCancellation() + { + using CancellationTokenSource cts = new(); + cts.Cancel(); + + bool canceled = false; + + try + { + await DismApi.MountImageAsync(InstallWimPath.FullName, MountPath.FullName, imageName: "FakeImage", readOnly: true, options: DismMountImageOptions.None, progress: null, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + canceled = true; + } + + canceled.ShouldBeTrue(); + } + + [Fact] + public async Task MountImageAsyncInstallWim() + { + await DismApi.MountImageAsync(InstallWimPath.FullName, MountPath.FullName, imageIndex: 1, readOnly: true, DismMountImageOptions.None, progress: null, TestContext.Current.CancellationToken); + + await DismApi.UnmountImageAsync(MountPath.FullName, commitChanges: false, progress: null, cancellationToken: TestContext.Current.CancellationToken); + } + + [Fact] + public async Task MountImageAsyncWithProgress() + { + bool progressCalled = false; + + using CancellationTokenSource cts = new(); + + Progress progress = new(_ => + { + progressCalled = true; + }); + + await DismApi.MountImageAsync(InstallWimPath.FullName, MountPath.FullName, imageIndex: 1, readOnly: true, options: DismMountImageOptions.None, progress: progress, cancellationToken: cts.Token); + + try + { + progressCalled.ShouldBeTrue(); + } + finally + { + await DismApi.UnmountImageAsync(MountPath.FullName, commitChanges: false, progress: null, TestContext.Current.CancellationToken); + } + } + } +} diff --git a/src/Microsoft.Dism.Tests/RemoveCapabilityAsyncTest.cs b/src/Microsoft.Dism.Tests/RemoveCapabilityAsyncTest.cs deleted file mode 100644 index fbf955b..0000000 --- a/src/Microsoft.Dism.Tests/RemoveCapabilityAsyncTest.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c). All rights reserved. -// -// Licensed under the MIT license. -#if !NETFRAMEWORK -using Shouldly; -using System; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Dism.Tests -{ - public class RemoveCapabilityAsyncTest : DismTestBase - { - public RemoveCapabilityAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) - : base(template, testOutput) - { - } - - [Fact] - public async Task RemoveCapabilityAsyncCancellation() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.RemoveCapabilityAsync(session, "FakeCapability", cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task RemoveCapabilityAsyncWithProgress() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - - SynchronousProgress progress = new(_ => - { - cts.Cancel(); - }); - - try - { - await DismApi.RemoveCapabilityAsync(session, "FakeCapability", progress: progress, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - } - catch (DismException) - { - // Expected when the capability does not exist - } - - // Progress may not be called for an invalid capability, so we just verify no hang occurred - } - - private sealed class SynchronousProgress : IProgress - { - private readonly Action _handler; - - public SynchronousProgress(Action handler) - { - _handler = handler; - } - - public void Report(T value) - { - _handler(value); - } - } - } -} -#endif diff --git a/src/Microsoft.Dism.Tests/RemovePackageAsyncTest.cs b/src/Microsoft.Dism.Tests/RemovePackageAsyncTest.cs deleted file mode 100644 index e609256..0000000 --- a/src/Microsoft.Dism.Tests/RemovePackageAsyncTest.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c). All rights reserved. -// -// Licensed under the MIT license. -#if !NETFRAMEWORK -using Shouldly; -using System; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Dism.Tests -{ - public class RemovePackageAsyncTest : DismTestBase - { - public RemovePackageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) - : base(template, testOutput) - { - } - - [Fact] - public async Task RemovePackageByNameAsyncCancellation() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.RemovePackageByNameAsync(session, "FakePackage", cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task RemovePackageByPathAsyncCancellation() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.RemovePackageByPathAsync(session, "nonexistent.cab", cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task RemovePackageByNameAsyncWithProgress() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - - SynchronousProgress progress = new(_ => - { - cts.Cancel(); - }); - - try - { - await DismApi.RemovePackageByNameAsync(session, "FakePackage", progress: progress, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - } - catch (DismException) - { - // Expected when the package does not exist - } - - // Progress may not be called for an invalid package, so we just verify no hang occurred - } - - private sealed class SynchronousProgress : IProgress - { - private readonly Action _handler; - - public SynchronousProgress(Action handler) - { - _handler = handler; - } - - public void Report(T value) - { - _handler(value); - } - } - } -} -#endif diff --git a/src/Microsoft.Dism.Tests/RestoreImageHealthAsyncTest.cs b/src/Microsoft.Dism.Tests/RestoreImageHealthAsyncTest.cs deleted file mode 100644 index d162b77..0000000 --- a/src/Microsoft.Dism.Tests/RestoreImageHealthAsyncTest.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c). All rights reserved. -// -// Licensed under the MIT license. -#if !NETFRAMEWORK -using Shouldly; -using System; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Dism.Tests -{ - public class RestoreImageHealthAsyncTest : DismTestBase - { - public RestoreImageHealthAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) - : base(template, testOutput) - { - } - - [Fact] - public async Task RestoreImageHealthAsyncCancellation() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.RestoreImageHealthAsync(session, limitAccess: true, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task RestoreImageHealthAsyncWithProgress() - { - using DismSession session = DismApi.OpenOnlineSession(); - using CancellationTokenSource cts = new(); - - SynchronousProgress progress = new(_ => - { - cts.Cancel(); - }); - - try - { - await DismApi.RestoreImageHealthAsync(session, limitAccess: true, progress: progress, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - } - - // Progress may or may not be called depending on image state, so we just verify no hang occurred - } - - private sealed class SynchronousProgress : IProgress - { - private readonly Action _handler; - - public SynchronousProgress(Action handler) - { - _handler = handler; - } - - public void Report(T value) - { - _handler(value); - } - } - } -} -#endif diff --git a/src/Microsoft.Dism.Tests/SetEditionAsyncTest.cs b/src/Microsoft.Dism.Tests/SetEditionAsyncTest.cs deleted file mode 100644 index 02989cb..0000000 --- a/src/Microsoft.Dism.Tests/SetEditionAsyncTest.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c). All rights reserved. -// -// Licensed under the MIT license. -#if !NETFRAMEWORK -using Shouldly; -using System; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Dism.Tests -{ - public class SetEditionAsyncTest : DismInstallWimTestBase - { - public SetEditionAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) - : base(template, testOutput) - { - } - - [Fact] - public async Task SetEditionAsyncCancellation() - { - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.SetEditionAsync(Session, "FakeEdition", cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task SetEditionAndProductKeyAsyncCancellation() - { - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.SetEditionAndProductKeyAsync(Session, "FakeEdition", "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX", cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task SetEditionAsyncWithProgress() - { - using CancellationTokenSource cts = new(); - - SynchronousProgress progress = new(_ => - { - cts.Cancel(); - }); - - try - { - await DismApi.SetEditionAsync(Session, "FakeEdition", progress: progress, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - } - catch (DismException) - { - // Expected when the edition does not exist - } - - // Progress may not be called for an invalid edition, so we just verify no hang occurred - } - - private sealed class SynchronousProgress : IProgress - { - private readonly Action _handler; - - public SynchronousProgress(Action handler) - { - _handler = handler; - } - - public void Report(T value) - { - _handler(value); - } - } - } -} -#endif diff --git a/src/Microsoft.Dism.Tests/TestWimTemplate.cs b/src/Microsoft.Dism.Tests/TestWimTemplate.cs index 5994188..d0a2bc0 100644 --- a/src/Microsoft.Dism.Tests/TestWimTemplate.cs +++ b/src/Microsoft.Dism.Tests/TestWimTemplate.cs @@ -87,7 +87,7 @@ private string CaptureTemplateImage(string capturePath) using WimHandle imageHandle = WimgApi.CaptureImage(wimHandle, capturePath, WimCaptureImageOptions.DisableDirectoryAcl | WimCaptureImageOptions.DisableFileAcl | WimCaptureImageOptions.DisableRPFix); } - XPathNavigator xml = WimgApi.GetImageInformation(wimHandle!) !.CreateNavigator() !; + XPathNavigator xml = WimgApi.GetImageInformation(wimHandle!)!.CreateNavigator()!; xml.ShouldNotBeNull(); @@ -172,7 +172,7 @@ private string CreateTemplateImage() } } - [CollectionDefinition(nameof(TestWimTemplate))] + [CollectionDefinition(nameof(TestWimTemplate), DisableParallelization = true)] public class TestWimTemplateCollectionDefinition : ICollectionFixture { } diff --git a/src/Microsoft.Dism.Tests/UnmountImageAsyncTest.cs b/src/Microsoft.Dism.Tests/UnmountImageAsyncTest.cs deleted file mode 100644 index 3829b38..0000000 --- a/src/Microsoft.Dism.Tests/UnmountImageAsyncTest.cs +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c). All rights reserved. -// -// Licensed under the MIT license. -#if !NETFRAMEWORK -using Shouldly; -using System; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Dism.Tests -{ - public class UnmountImageAsyncTest : DismTestBase - { - public UnmountImageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) - : base(template, testOutput) - { - } - - [Fact] - public async Task UnmountImageAsyncCancellation() - { - using CancellationTokenSource cts = new(); - cts.Cancel(); - - bool canceled = false; - - try - { - await DismApi.UnmountImageAsync(MountPath.FullName, commitChanges: false, cancellationToken: cts.Token); - } - catch (OperationCanceledException) - { - canceled = true; - } - - canceled.ShouldBeTrue(); - } - - [Fact] - public async Task UnmountImageAsyncWithProgress() - { - // Mount an image first so we can unmount it - foreach (DismMountedImageInfo mountedImageInfo in DismApi.GetMountedImages()) - { - DismApi.UnmountImage(mountedImageInfo.MountPath, false); - } - - DismApi.CleanupMountpoints(); - DismApi.MountImage(InstallWimPath.FullName, MountPath.FullName, 1); - - using CancellationTokenSource cts = new(); - - SynchronousProgress progress = new(_ => - { - }); - - try - { - await DismApi.UnmountImageAsync(MountPath.FullName, commitChanges: false, progress: progress, cancellationToken: cts.Token); - } - catch (DismException) - { - // Attempt to clean up - try - { - DismApi.UnmountImage(MountPath.FullName, commitChanges: false); - } - catch - { - // Best effort cleanup - } - } - - // Progress may or may not be called depending on image size - } - - [Fact] - public async Task UnmountImageAsyncHappyPath() - { - // Mount an image first so we can unmount it - foreach (DismMountedImageInfo mountedImageInfo in DismApi.GetMountedImages()) - { - DismApi.UnmountImage(mountedImageInfo.MountPath, false); - } - - DismApi.CleanupMountpoints(); - DismApi.MountImage(InstallWimPath.FullName, MountPath.FullName, 1); - - await DismApi.UnmountImageAsync(MountPath.FullName, commitChanges: false, cancellationToken: TestContext.Current.CancellationToken); - } - - private sealed class SynchronousProgress : IProgress - { - private readonly Action _handler; - - public SynchronousProgress(Action handler) - { - _handler = handler; - } - - public void Report(T value) - { - _handler(value); - } - } - } -} -#endif diff --git a/src/Microsoft.Dism/CallerMemberNameAttribute.cs b/src/Microsoft.Dism/CallerMemberNameAttribute.cs deleted file mode 100644 index d5432d0..0000000 --- a/src/Microsoft.Dism/CallerMemberNameAttribute.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c). All rights reserved. -// -// Licensed under the MIT license. - -#if NET40 -namespace System.Runtime.CompilerServices -{ - /// - /// Allows you to obtain the method or property name of the caller to the method. - /// - [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] - internal class CallerMemberNameAttribute : Attribute - { - } -} -#endif \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.AddCapability.cs b/src/Microsoft.Dism/DismApi.AddCapability.cs index 2d897ec..903befc 100644 --- a/src/Microsoft.Dism/DismApi.AddCapability.cs +++ b/src/Microsoft.Dism/DismApi.AddCapability.cs @@ -5,6 +5,7 @@ using Microsoft.Win32.SafeHandles; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; @@ -52,20 +53,14 @@ public static void AddCapability(DismSession session, string capabilityName, boo /// Optional user data to pass to the DismProgressCallback method. /// When a failure occurs. /// When the operation requires a reboot to complete. - public static void AddCapability(DismSession session, string capabilityName, bool limitAccess, List? sourcePaths, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) + public static void AddCapability(DismSession session, string capabilityName, bool limitAccess, List? sourcePaths, DismProgressCallback? progressCallback, object? userData) { - // Get the list of source paths as an array - string[] sourcePathsArray = sourcePaths?.ToArray() ?? []; - // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new(progressCallback, userData); + using DismProgress progress = new(progressCallback, userData); - int hresult = NativeMethods.DismAddCapability(session, capabilityName, limitAccess, sourcePathsArray, (uint)sourcePathsArray.Length, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); - - DismUtilities.ThrowIfFail(hresult, session); + AddCapability(session, capabilityName, limitAccess, sourcePaths, progress); } -#if !NET40 /// /// Asynchronously adds a capability to an image. /// @@ -73,61 +68,70 @@ public static void AddCapability(DismSession session, string capabilityName, boo /// The name of the capability that is being added. /// The flag indicates whether WU/WSUS should be contacted as a source location for downloading the payload of a capability. If payload of the capability to be added exists, the flag is ignored. /// A list of source locations. The function shall look up removed payload files from the locations specified in SourcePaths, and if not found, continue the search by contacting WU/WSUS depending on parameter LimitAccess. - /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. + /// A token to monitor for cancellation requests. The default value is . /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. /// When the operation requires a reboot to complete. - public static Task AddCapabilityAsync(DismSession session, string capabilityName, bool limitAccess, List? sourcePaths, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task AddCapabilityAsync(DismSession session, string capabilityName, bool limitAccess, List? sourcePaths, CancellationToken cancellationToken = default) { - TaskCompletionSource tcs = new(); + return AddCapabilityAsync(session, capabilityName, limitAccess, sourcePaths, progress: null, cancellationToken); + } - CancellationTokenRegistration ctsRegistration = default; + /// + /// Asynchronously adds a capability to an image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. + /// The name of the capability that is being added. + /// The flag indicates whether WU/WSUS should be contacted as a source location for downloading the payload of a capability. If payload of the capability to be added exists, the flag is ignored. + /// A list of source locations. The function shall look up removed payload files from the locations specified in SourcePaths, and if not found, continue the search by contacting WU/WSUS depending on parameter LimitAccess. + /// An optional provider to receive progress updates. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task AddCapabilityAsync(DismSession session, string capabilityName, bool limitAccess, List? sourcePaths, IProgress? progress, CancellationToken cancellationToken = default) + { + return AddCapabilityAsync(session, capabilityName, limitAccess, sourcePaths, progress, userData: null, cancellationToken); + } - Task.Factory.StartNew( - () => + /// + /// Asynchronously adds a capability to an image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. + /// The name of the capability that is being added. + /// The flag indicates whether WU/WSUS should be contacted as a source location for downloading the payload of a capability. If payload of the capability to be added exists, the flag is ignored. + /// A list of source locations. The function shall look up removed payload files from the locations specified in SourcePaths, and if not found, continue the search by contacting WU/WSUS depending on parameter LimitAccess. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task AddCapabilityAsync(DismSession session, string capabilityName, bool limitAccess, List? sourcePaths, IProgress? progress, object? userData, CancellationToken cancellationToken = default) + { + return DismUtilities.RunAsync( + static (state, progress) => { - try - { - string[] sourcePathsArray = sourcePaths?.ToArray() ?? []; - - DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); + AddCapability(state.session, state.capabilityName, state.limitAccess, state.sourcePaths, progress); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + return true; + }, + (session, capabilityName, limitAccess, sourcePaths), + progress, userData, cancellationToken); + } - int hresult = NativeMethods.DismAddCapability(session, capabilityName, limitAccess, sourcePathsArray, (uint)sourcePathsArray.Length, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + private static void AddCapability(DismSession session, string capabilityName, bool limitAccess, List? sourcePaths, DismProgress progress) + { + // Get the list of source paths as an array + string[] sourcePathsArray = sourcePaths?.ToArray() ?? []; - if (cancellationToken.IsCancellationRequested) - { - tcs.TrySetCanceled(cancellationToken); - } - else - { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); - } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - CancellationToken.None, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + int hresult = NativeMethods.DismAddCapability(session, capabilityName, limitAccess, sourcePathsArray, (uint)sourcePathsArray.Length, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); - return tcs.Task; + DismUtilities.ThrowIfFail(hresult, session); } -#endif internal static partial class NativeMethods { @@ -143,17 +147,23 @@ internal static partial class NativeMethods /// Pointer to a client defined callback function to report progress. /// User defined custom data. This will be passed back to the user through the callback. /// Returns S_OK on success. - /// - /// - /// HRESULT WINAPI DismAddCapability(_In_ DismSession Session, _In_ PCWSTR Name, _In_ BOOL LimitAccess, _In_ PCWSTR* SourcePaths, _In_opt_ UINT SourcePathCount, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); - /// - #if NET7_0_OR_GREATER + /// HRESULT WINAPI DismAddCapability(_In_ DismSession Session, _In_ PCWSTR Name, _In_ BOOL LimitAccess, _In_ PCWSTR* SourcePaths, _In_opt_ UINT SourcePathCount, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); +#if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismAddCapability(DismSession session, string name, [MarshalAs(UnmanagedType.Bool)] bool limitAccess, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 6)] string[] sourcePaths, UInt32 sourcePathCount, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismAddCapability(DismSession session, string name, [MarshalAs(UnmanagedType.Bool)] bool limitAccess, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 6)] string[] sourcePaths, UInt32 sourcePathCount, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #endif + public static extern +#endif + int DismAddCapability( + DismSession session, + string name, + [MarshalAs(UnmanagedType.Bool)] bool limitAccess, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 6)] string[] sourcePaths, + UInt32 sourcePathCount, + SafeWaitHandle cancelEvent, + DismProgressCallbackNative progress, + IntPtr userData); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Dism/DismApi.AddDriver.cs b/src/Microsoft.Dism/DismApi.AddDriver.cs index 4a2e936..607c461 100644 --- a/src/Microsoft.Dism/DismApi.AddDriver.cs +++ b/src/Microsoft.Dism/DismApi.AddDriver.cs @@ -30,7 +30,7 @@ public static void AddDriver(DismSession session, string driverPath, bool forceU /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. /// A relative or absolute path to a directory containing driver .inf files. /// Indicates whether to accept unsigned drivers to an x64-based image. Unsigned drivers will automatically be added to an x86-based image. - /// true to search recursively for driver files, otherwise false. + /// to search recursively for driver files, otherwise to only enumrate the specified directory. /// The directory specified by the parameter does not exist. public static void AddDriversEx(DismSession session, string driverDirectory, bool forceUnsigned, bool recursive) { @@ -55,11 +55,15 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismAddDriver(DismSession session, string driverPath, [MarshalAs(UnmanagedType.Bool)] bool forceUnsigned); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismAddDriver(DismSession session, string driverPath, [MarshalAs(UnmanagedType.Bool)] bool forceUnsigned); - #endif + public static extern +#endif + int DismAddDriver( + DismSession session, + string driverPath, + [MarshalAs(UnmanagedType.Bool)] bool forceUnsigned); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.AddPackage.cs b/src/Microsoft.Dism/DismApi.AddPackage.cs index d952236..3f85eb6 100644 --- a/src/Microsoft.Dism/DismApi.AddPackage.cs +++ b/src/Microsoft.Dism/DismApi.AddPackage.cs @@ -39,7 +39,7 @@ public static void AddPackage(DismSession session, string packagePath, bool igno /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. /// When the package is not applicable to the specified session. - public static void AddPackage(DismSession session, string packagePath, bool ignoreCheck, bool preventPending, Microsoft.Dism.DismProgressCallback? progressCallback) + public static void AddPackage(DismSession session, string packagePath, bool ignoreCheck, bool preventPending, DismProgressCallback? progressCallback) { AddPackage(session, packagePath, ignoreCheck, preventPending, progressCallback, userData: null); } @@ -57,17 +57,14 @@ public static void AddPackage(DismSession session, string packagePath, bool igno /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. /// When the package is not applicable to the specified session. - public static void AddPackage(DismSession session, string packagePath, bool ignoreCheck, bool preventPending, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) + public static void AddPackage(DismSession session, string packagePath, bool ignoreCheck, bool preventPending, DismProgressCallback? progressCallback, object? userData) { // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new(progressCallback, userData); + using DismProgress progress = new(progressCallback, userData); - int hresult = NativeMethods.DismAddPackage(session, packagePath, ignoreCheck, preventPending, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); - - DismUtilities.ThrowIfFail(hresult, session); + AddPackage(session, packagePath, ignoreCheck, preventPending, progress); } -#if !NET40 /// /// Asynchronously adds a single .cab or .msu file to a Windows® image. /// @@ -75,60 +72,72 @@ public static void AddPackage(DismSession session, string packagePath, bool igno /// A relative or absolute path to the .cab or .msu file being added or a folder containing the expanded files of a single .cab file. /// Specifies whether to ignore the internal applicability checks that are done when a package is added. /// Specifies whether to add a package if it has pending online actions. - /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. + /// A token to monitor for cancellation requests. The default value is . /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. /// When the operation requires a reboot to complete. /// When the package is not applicable to the specified session. - public static Task AddPackageAsync(DismSession session, string packagePath, bool ignoreCheck, bool preventPending, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task AddPackageAsync(DismSession session, string packagePath, bool ignoreCheck, bool preventPending, CancellationToken cancellationToken = default) { - TaskCompletionSource tcs = new(); + return AddPackageAsync(session, packagePath, ignoreCheck, preventPending, progress: null, cancellationToken); + } - CancellationTokenRegistration ctsRegistration = default; + /// + /// Asynchronously adds a single .cab or .msu file to a Windows® image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the OpenSession method. + /// A relative or absolute path to the .cab or .msu file being added or a folder containing the expanded files of a single .cab file. + /// Specifies whether to ignore the internal applicability checks that are done when a package is added. + /// Specifies whether to add a package if it has pending online actions. + /// An optional provider to receive progress updates. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + /// When the package is not applicable to the specified session. + public static Task AddPackageAsync(DismSession session, string packagePath, bool ignoreCheck, bool preventPending, IProgress? progress, CancellationToken cancellationToken = default) + { + return AddPackageAsync(session, packagePath, ignoreCheck, preventPending, progress, userData: null, cancellationToken); + } - Task.Factory.StartNew( - () => + /// + /// Asynchronously adds a single .cab or .msu file to a Windows® image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the OpenSession method. + /// A relative or absolute path to the .cab or .msu file being added or a folder containing the expanded files of a single .cab file. + /// Specifies whether to ignore the internal applicability checks that are done when a package is added. + /// Specifies whether to add a package if it has pending online actions. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + /// When the package is not applicable to the specified session. + public static Task AddPackageAsync(DismSession session, string packagePath, bool ignoreCheck, bool preventPending, IProgress? progress, object? userData, CancellationToken cancellationToken = default) + { + return DismUtilities.RunAsync( + static (state, progress) => { - try - { - DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); - - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - - int hresult = NativeMethods.DismAddPackage(session, packagePath, ignoreCheck, preventPending, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + AddPackage(state.session, state.packagePath, state.ignoreCheck, state.preventPending, progress); - if (cancellationToken.IsCancellationRequested) - { - tcs.TrySetCanceled(cancellationToken); - } - else - { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); - } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } + return true; }, - CancellationToken.None, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + (session, packagePath, ignoreCheck, preventPending), + progress, + userData, + cancellationToken); + } + + private static void AddPackage(DismSession session, string packagePath, bool ignoreCheck, bool preventPending, DismProgress progress) + { + int hresult = NativeMethods.DismAddPackage(session, packagePath, ignoreCheck, preventPending, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); - return tcs.Task; + DismUtilities.ThrowIfFail(hresult, session); } -#endif internal static partial class NativeMethods { @@ -143,19 +152,26 @@ internal static partial class NativeMethods /// Optional. A pointer to a client-defined DismProgressCallback Function. /// Optional. User defined custom data. /// Returns S_OK on success. - /// Only .cab files can be added to an online image. Either .cab or .msu files can be added to an offline image. + /// + /// Only .cab files can be added to an online image. Either .cab or .msu files can be added to an offline image. /// - /// This function will return a special error code if the package is not applicable. You can use the DismGetPackageInfo Function to determine if a package is applicable to the target image. - /// - /// HRESULT WINAPI DismAddPackage (_In_ DismSession Session, _In_ PCWSTR PackagePath, _In_ BOOL IgnoreCheck, _In_ BOOL PreventPending _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData) + /// This function will return a special error code if the package is not applicable. You can use the DismGetPackageInfo Function to determine if a package is applicable to the target image. HRESULT WINAPI DismAddPackage (_In_ DismSession Session, _In_ PCWSTR PackagePath, _In_ BOOL IgnoreCheck, _In_ BOOL PreventPending _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData) /// - #if NET7_0_OR_GREATER +#if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismAddPackage(DismSession session, string packagePath, [MarshalAs(UnmanagedType.Bool)] bool ignoreCheck, [MarshalAs(UnmanagedType.Bool)] bool preventPending, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismAddPackage(DismSession session, string packagePath, [MarshalAs(UnmanagedType.Bool)] bool ignoreCheck, [MarshalAs(UnmanagedType.Bool)] bool preventPending, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #endif + public static extern +#endif + int DismAddPackage( + DismSession session, + string packagePath, + [MarshalAs(UnmanagedType.Bool)] bool ignoreCheck, + [MarshalAs(UnmanagedType.Bool)] bool preventPending, + SafeWaitHandle cancelEvent, + DismProgressCallbackNative progress, + IntPtr userData); } } } diff --git a/src/Microsoft.Dism/DismApi.AddProvisionedAppxPackage.cs b/src/Microsoft.Dism/DismApi.AddProvisionedAppxPackage.cs index ecf1321..54eb674 100644 --- a/src/Microsoft.Dism/DismApi.AddProvisionedAppxPackage.cs +++ b/src/Microsoft.Dism/DismApi.AddProvisionedAppxPackage.cs @@ -122,28 +122,12 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int _DismAddProvisionedAppxPackage( - DismSession Session, - [MarshalAs(UnmanagedType.LPWStr)] - string AppPath, - [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 3)] - string[] DependencyPackages, - uint DependencyPackageCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 5)] - string[] OptionalPackages, - uint OptionalPackageCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 7)] - string[] LicensePaths, - uint LicensePathCount, - [MarshalAs(UnmanagedType.Bool)] bool SkipLicense, - [MarshalAs(UnmanagedType.LPWStr)] - string CustomDataPath, - [MarshalAs(UnmanagedType.LPWStr)] - string? Regions, - DismStubPackageOption stubPackageOption); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int _DismAddProvisionedAppxPackage( + public static extern +#endif + int _DismAddProvisionedAppxPackage( DismSession Session, [MarshalAs(UnmanagedType.LPWStr)] string AppPath, @@ -156,13 +140,12 @@ public static extern int _DismAddProvisionedAppxPackage( [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 7)] string[] LicensePaths, uint LicensePathCount, - bool SkipLicense, + [MarshalAs(UnmanagedType.Bool)] bool SkipLicense, [MarshalAs(UnmanagedType.LPWStr)] string CustomDataPath, [MarshalAs(UnmanagedType.LPWStr)] string? Regions, DismStubPackageOption stubPackageOption); - #endif } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.ApplyFfuImage.cs b/src/Microsoft.Dism/DismApi.ApplyFfuImage.cs index 6bbb0a1..1657483 100644 --- a/src/Microsoft.Dism/DismApi.ApplyFfuImage.cs +++ b/src/Microsoft.Dism/DismApi.ApplyFfuImage.cs @@ -40,11 +40,15 @@ internal static partial class NativeMethods /// Returns S_OK on success. #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int _DismApplyFfuImage([MarshalAs(UnmanagedType.LPWStr)] string ImagePath, [MarshalAs(UnmanagedType.LPWStr)] string ApplyPath, [MarshalAs(UnmanagedType.LPWStr)] string PartPath); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int _DismApplyFfuImage([MarshalAs(UnmanagedType.LPWStr)] string ImagePath, [MarshalAs(UnmanagedType.LPWStr)] string ApplyPath, [MarshalAs(UnmanagedType.LPWStr)] string PartPath); - #endif + public static extern +#endif + int _DismApplyFfuImage( + [MarshalAs(UnmanagedType.LPWStr)] string ImagePath, + [MarshalAs(UnmanagedType.LPWStr)] string ApplyPath, + [MarshalAs(UnmanagedType.LPWStr)] string PartPath); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.ApplyUnattend.cs b/src/Microsoft.Dism/DismApi.ApplyUnattend.cs index 219e0b6..56a62f9 100644 --- a/src/Microsoft.Dism/DismApi.ApplyUnattend.cs +++ b/src/Microsoft.Dism/DismApi.ApplyUnattend.cs @@ -37,11 +37,15 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismApplyUnattend(DismSession session, string unattendFile, [MarshalAs(UnmanagedType.Bool)] bool singleSession); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismApplyUnattend(DismSession session, string unattendFile, [MarshalAs(UnmanagedType.Bool)] bool singleSession); - #endif + public static extern +#endif + int DismApplyUnattend( + DismSession session, + string unattendFile, + [MarshalAs(UnmanagedType.Bool)] bool singleSession); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.CheckImageHealth.cs b/src/Microsoft.Dism/DismApi.CheckImageHealth.cs index f1ed48f..a707a7b 100644 --- a/src/Microsoft.Dism/DismApi.CheckImageHealth.cs +++ b/src/Microsoft.Dism/DismApi.CheckImageHealth.cs @@ -33,7 +33,7 @@ public static DismImageHealthState CheckImageHealth(DismSession session, bool sc /// A indicating the health state of the image. /// When a failure occurs. /// When the user requested the operation be canceled. - public static DismImageHealthState CheckImageHealth(DismSession session, bool scanImage, Microsoft.Dism.DismProgressCallback? progressCallback) + public static DismImageHealthState CheckImageHealth(DismSession session, bool scanImage, DismProgressCallback? progressCallback) { return CheckImageHealth(session, scanImage, progressCallback, userData: null); } @@ -48,76 +48,77 @@ public static DismImageHealthState CheckImageHealth(DismSession session, bool sc /// A indicating the health state of the image. /// When a failure occurs. /// When the user requested the operation be canceled. - public static DismImageHealthState CheckImageHealth(DismSession session, bool scanImage, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) + public static DismImageHealthState CheckImageHealth(DismSession session, bool scanImage, DismProgressCallback? progressCallback, object? userData) { // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new(progressCallback, userData); + using DismProgress progress = new(progressCallback, userData); - int hresult = NativeMethods.DismCheckImageHealth(session, scanImage, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero, out DismImageHealthState imageHealthState); - - DismUtilities.ThrowIfFail(hresult, session); + return CheckImageHealth(session, scanImage, progress); + } - return imageHealthState; + /// + /// Asynchronously checks whether the image can be serviced or whether it is corrupted. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// Specifies whether to scan the image or just check for flags from a previous scan. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation, containing the health state of the image. + /// When a failure occurs. + /// When the operation is canceled. + public static Task CheckImageHealthAsync(DismSession session, bool scanImage, CancellationToken cancellationToken = default) + { + return CheckImageHealthAsync(session, scanImage, progress: null, cancellationToken); } -#if !NET40 /// /// Asynchronously checks whether the image can be serviced or whether it is corrupted. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// Specifies whether to scan the image or just check for flags from a previous scan. /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. + /// A token to monitor for cancellation requests. The default value is . /// A representing the asynchronous operation, containing the health state of the image. /// When a failure occurs. /// When the operation is canceled. - public static Task CheckImageHealthAsync(DismSession session, bool scanImage, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task CheckImageHealthAsync(DismSession session, bool scanImage, IProgress? progress, CancellationToken cancellationToken = default) { - TaskCompletionSource tcs = new(); - - CancellationTokenRegistration ctsRegistration = default; + return CheckImageHealthAsync(session, scanImage, progress, userData: null, cancellationToken); + } - Task.Factory.StartNew( - () => + /// + /// Asynchronously checks whether the image can be serviced or whether it is corrupted. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// Specifies whether to scan the image or just check for flags from a previous scan. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation, containing the health state of the image. + /// When a failure occurs. + /// When the operation is canceled. + public static Task CheckImageHealthAsync(DismSession session, bool scanImage, IProgress? progress, object? userData, CancellationToken cancellationToken = default) + { + return DismUtilities.RunAsync( + static (state, progress) => { - try - { - DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); + DismImageHealthState imageHealthState = CheckImageHealth(state.session, state.scanImage, progress); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + return imageHealthState; + }, + (session, scanImage), + progress, + userData, + cancellationToken); + } - int hresult = NativeMethods.DismCheckImageHealth(session, scanImage, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero, out DismImageHealthState imageHealthState); + private static DismImageHealthState CheckImageHealth(DismSession session, bool scanImage, DismProgress progress) + { + int hresult = NativeMethods.DismCheckImageHealth(session, scanImage, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero, out DismImageHealthState imageHealthState); - if (cancellationToken.IsCancellationRequested) - { - tcs.TrySetCanceled(cancellationToken); - } - else - { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(imageHealthState); - } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - CancellationToken.None, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + DismUtilities.ThrowIfFail(hresult, session); - return tcs.Task; + return imageHealthState; } -#endif internal static partial class NativeMethods { @@ -131,18 +132,25 @@ internal static partial class NativeMethods /// Optional. User defined custom data. /// A pointer to the DismImageHealthState Enumeration. The enumeration value is set during this operation. /// Returns S_OK on success. - /// If ScanImage is set to True, this function will take longer to finish. + /// + /// If ScanImage is set to True, this function will take longer to finish. /// - /// - /// HRESULT WINAPI DismCheckImageHealth(_In_ DismSession Session, _In_ BOOL ScanImage, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData, _Out_ DismImageHealthState* ImageHealth); + /// HRESULT WINAPI DismCheckImageHealth(_In_ DismSession Session, _In_ BOOL ScanImage, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData, _Out_ DismImageHealthState* ImageHealth); /// - #if NET7_0_OR_GREATER +#if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismCheckImageHealth(DismSession session, [MarshalAs(UnmanagedType.Bool)] bool scanImage, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData, out DismImageHealthState imageHealth); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismCheckImageHealth(DismSession session, [MarshalAs(UnmanagedType.Bool)] bool scanImage, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData, out DismImageHealthState imageHealth); - #endif + public static extern +#endif + int DismCheckImageHealth( + DismSession session, + [MarshalAs(UnmanagedType.Bool)] bool scanImage, + SafeWaitHandle cancelEvent, + DismProgressCallbackNative progress, + IntPtr userData, + out DismImageHealthState imageHealth); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Dism/DismApi.CleanupMountpoints.cs b/src/Microsoft.Dism/DismApi.CleanupMountpoints.cs index 44cc2d9..c99571d 100644 --- a/src/Microsoft.Dism/DismApi.CleanupMountpoints.cs +++ b/src/Microsoft.Dism/DismApi.CleanupMountpoints.cs @@ -30,11 +30,12 @@ internal static partial class NativeMethods /// HRESULT WINAPI DismCleanupMountpoints( ); #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismCleanupMountpoints(); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismCleanupMountpoints(); - #endif + public static extern +#endif + int DismCleanupMountpoints(); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.CloseSession.cs b/src/Microsoft.Dism/DismApi.CloseSession.cs index f32b035..0f82da8 100644 --- a/src/Microsoft.Dism/DismApi.CloseSession.cs +++ b/src/Microsoft.Dism/DismApi.CloseSession.cs @@ -38,11 +38,13 @@ internal static partial class NativeMethods /// HRESULT WINAPI DismCloseSession(_In_ DismSession Session); #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismCloseSession(IntPtr session); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismCloseSession(IntPtr session); - #endif + public static extern +#endif + int DismCloseSession( + IntPtr session); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.CommitImage.cs b/src/Microsoft.Dism/DismApi.CommitImage.cs index 37d79fa..79bc7f4 100644 --- a/src/Microsoft.Dism/DismApi.CommitImage.cs +++ b/src/Microsoft.Dism/DismApi.CommitImage.cs @@ -16,7 +16,7 @@ public static partial class DismApi /// Commits the changes made to a Windows® image in a mounted .wim or .vhd file. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. - /// true or false to discard changes made to the image. + /// to discard changes made to the image, otherwise to keep changes made to the image. /// When a failure occurs. public static void CommitImage(DismSession session, bool discardChanges) { @@ -27,11 +27,11 @@ public static void CommitImage(DismSession session, bool discardChanges) /// Commits the changes made to a Windows® image in a mounted .wim or .vhd file. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. - /// true or false to discard changes made to the image. + /// to discard changes made to the image, otherwise to keep changes made to the image. /// A progress callback method to invoke when progress is made. /// When a failure occurs. /// When the user requested the operation be canceled. - public static void CommitImage(DismSession session, bool discardChanges, Microsoft.Dism.DismProgressCallback? progressCallback) + public static void CommitImage(DismSession session, bool discardChanges, DismProgressCallback? progressCallback) { CommitImage(session, discardChanges, progressCallback, userData: null); } @@ -40,84 +40,81 @@ public static void CommitImage(DismSession session, bool discardChanges, Microso /// Commits the changes made to a Windows® image in a mounted .wim or .vhd file. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. - /// true or false to discard changes made to the image. + /// to discard changes made to the image, otherwise to keep changes made to the image. /// A progress callback method to invoke when progress is made. /// Optional user data to pass to the DismProgressCallback method. /// When a failure occurs. /// When the user requested the operation be canceled. - public static void CommitImage(DismSession session, bool discardChanges, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) + public static void CommitImage(DismSession session, bool discardChanges, DismProgressCallback? progressCallback, object? userData) { - // Create the flags - UInt32 flags = discardChanges ? DISM_DISCARD_IMAGE : DISM_COMMIT_IMAGE; - - // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new(progressCallback, userData); + using DismProgress progress = new(progressCallback, userData); - int hresult = NativeMethods.DismCommitImage(session, flags, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); - - DismUtilities.ThrowIfFail(hresult, session); + CommitImage(session, discardChanges, progress); } -#if !NET40 /// /// Asynchronously commits the changes made to a Windows® image in a mounted .wim or .vhd file. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. - /// true or false to discard changes made to the image. - /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. + /// to discard changes made to the image, otherwise to keep changes made to the image. + /// A token to monitor for cancellation requests. The default value is . /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. - public static Task CommitImageAsync(DismSession session, bool discardChanges, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task CommitImageAsync(DismSession session, bool discardChanges, CancellationToken cancellationToken = default) { - TaskCompletionSource tcs = new(); + return CommitImageAsync(session, discardChanges, progress: null, cancellationToken); + } - CancellationTokenRegistration ctsRegistration = default; + /// + /// Asynchronously commits the changes made to a Windows® image in a mounted .wim or .vhd file. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. + /// to discard changes made to the image, otherwise to keep changes made to the image. + /// An optional provider to receive progress updates. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + public static Task CommitImageAsync(DismSession session, bool discardChanges, IProgress? progress, CancellationToken cancellationToken = default) + { + return CommitImageAsync(session, discardChanges, progress, userData: null, cancellationToken); + } - Task.Factory.StartNew( - () => + /// + /// Asynchronously commits the changes made to a Windows® image in a mounted .wim or .vhd file. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. + /// to discard changes made to the image, otherwise to keep changes made to the image. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + public static Task CommitImageAsync(DismSession session, bool discardChanges, IProgress? progress, object? userData, CancellationToken cancellationToken = default) + { + return DismUtilities.RunAsync( + static (state, progress) => { - try - { - UInt32 flags = discardChanges ? DISM_DISCARD_IMAGE : DISM_COMMIT_IMAGE; + CommitImage(state.session, state.discardChanges, progress); - DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); - - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + return true; + }, + (session, discardChanges), + progress, + userData, + cancellationToken); + } - int hresult = NativeMethods.DismCommitImage(session, flags, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + private static void CommitImage(DismSession session, bool discardChanges, DismProgress progress) + { + UInt32 flags = discardChanges ? DISM_DISCARD_IMAGE : DISM_COMMIT_IMAGE; - if (cancellationToken.IsCancellationRequested) - { - tcs.TrySetCanceled(cancellationToken); - } - else - { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); - } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - CancellationToken.None, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + int hresult = NativeMethods.DismCommitImage(session, flags, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); - return tcs.Task; + DismUtilities.ThrowIfFail(hresult, session); } -#endif internal static partial class NativeMethods { @@ -130,19 +127,24 @@ internal static partial class NativeMethods /// Optional. A pointer to a client-defined DismProgressCallback Function. /// Optional. User defined custom data. /// Returns S_OK on success. - /// The DismCommitImage function does not unmount the image. + /// + /// The DismCommitImage function does not unmount the image. /// DismCommitImage can only be used on an image that is mounted within the DISM infrastructure. It does not apply to images mounted by another tool, such as the DiskPart tool, which are serviced using the DismOpenSession Function. You must use the DismMountImage Function to mount an image within the DISM infrastructure. - /// - /// - /// HRESULT WINAPI DismCommitImage(_In_ DismSession Session, _In_ DWORD Flags, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); + /// HRESULT WINAPI DismCommitImage(_In_ DismSession Session, _In_ DWORD Flags, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); /// - #if NET7_0_OR_GREATER +#if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismCommitImage(DismSession session, UInt32 flags, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismCommitImage(DismSession session, UInt32 flags, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #endif + public static extern +#endif + int DismCommitImage( + DismSession session, + UInt32 flags, + SafeWaitHandle cancelEvent, + DismProgressCallbackNative progress, + IntPtr userData); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Dism/DismApi.Delete.cs b/src/Microsoft.Dism/DismApi.Delete.cs index 20359d4..d8e2eba 100644 --- a/src/Microsoft.Dism/DismApi.Delete.cs +++ b/src/Microsoft.Dism/DismApi.Delete.cs @@ -33,11 +33,13 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismDelete(IntPtr dismStructure); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismDelete(IntPtr dismStructure); - #endif + public static extern +#endif + int DismDelete( + IntPtr dismStructure); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.DisableFeature.cs b/src/Microsoft.Dism/DismApi.DisableFeature.cs index e25a0ce..33ac004 100644 --- a/src/Microsoft.Dism/DismApi.DisableFeature.cs +++ b/src/Microsoft.Dism/DismApi.DisableFeature.cs @@ -17,9 +17,11 @@ public static partial class DismApi /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that you want to disable. To disable more than one feature, separate each feature name with a semicolon. - /// Optional. The name of the parent package that the feature is a part of. + /// + /// Optional. The name of the parent package that the feature is a part of. /// - /// This is an optional parameter. If no package is specified, then the default Windows® Foundation package is used. + /// This is an optional parameter. If no package is specified, then the default Windows® Foundation package is used. + /// /// Specifies whether to remove the files required to enable the feature. /// When a failure occurs. /// When the operation requires a reboot to complete. @@ -33,15 +35,17 @@ public static void DisableFeature(DismSession session, string featureName, strin /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that you want to disable. To disable more than one feature, separate each feature name with a semicolon. - /// Optional. The name of the parent package that the feature is a part of. + /// + /// Optional. The name of the parent package that the feature is a part of. /// - /// This is an optional parameter. If no package is specified, then the default Windows® Foundation package is used. + /// This is an optional parameter. If no package is specified, then the default Windows® Foundation package is used. + /// /// Specifies whether to remove the files required to enable the feature. /// A progress callback method to invoke when progress is made. /// When a failure occurs. /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static void DisableFeature(DismSession session, string featureName, string packageName, bool removePayload, Microsoft.Dism.DismProgressCallback? progressCallback) + public static void DisableFeature(DismSession session, string featureName, string packageName, bool removePayload, DismProgressCallback? progressCallback) { DisableFeature(session, featureName, packageName, removePayload, progressCallback, userData: null); } @@ -51,88 +55,107 @@ public static void DisableFeature(DismSession session, string featureName, strin /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that you want to disable. To disable more than one feature, separate each feature name with a semicolon. - /// Optional. The name of the parent package that the feature is a part of. + /// + /// Optional. The name of the parent package that the feature is a part of. /// - /// This is an optional parameter. If no package is specified, then the default Windows® Foundation package is used. + /// This is an optional parameter. If no package is specified, then the default Windows® Foundation package is used. + /// /// Specifies whether to remove the files required to enable the feature. /// A progress callback method to invoke when progress is made. /// Optional user data to pass to the DismProgressCallback method. /// When a failure occurs. /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static void DisableFeature(DismSession session, string featureName, string packageName, bool removePayload, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) + public static void DisableFeature(DismSession session, string featureName, string packageName, bool removePayload, DismProgressCallback? progressCallback, object? userData) { // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new(progressCallback, userData); + using DismProgress progress = new(progressCallback, userData); - int hresult = NativeMethods.DismDisableFeature(session, featureName, packageName, removePayload, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); - - DismUtilities.ThrowIfFail(hresult, session); + DisableFeature(session, featureName, packageName, removePayload, progress); } -#if !NET40 /// /// Asynchronously disables a feature in the current image. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that you want to disable. To disable more than one feature, separate each feature name with a semicolon. - /// Optional. The name of the parent package that the feature is a part of. + /// + /// Optional. The name of the parent package that the feature is a part of. /// - /// This is an optional parameter. If no package is specified, then the default Windows® Foundation package is used. + /// This is an optional parameter. If no package is specified, then the default Windows® Foundation package is used. + /// /// Specifies whether to remove the files required to enable the feature. - /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. + /// A token to monitor for cancellation requests. The default value is . /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. /// When the operation requires a reboot to complete. - public static Task DisableFeatureAsync(DismSession session, string featureName, string packageName, bool removePayload, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task DisableFeatureAsync(DismSession session, string featureName, string packageName, bool removePayload, CancellationToken cancellationToken = default) { - TaskCompletionSource tcs = new(); + return DisableFeatureAsync(session, featureName, packageName, removePayload, progress: null, cancellationToken); + } - CancellationTokenRegistration ctsRegistration = default; + /// + /// Asynchronously disables a feature in the current image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that you want to disable. To disable more than one feature, separate each feature name with a semicolon. + /// + /// Optional. The name of the parent package that the feature is a part of. + /// + /// This is an optional parameter. If no package is specified, then the default Windows® Foundation package is used. + /// + /// Specifies whether to remove the files required to enable the feature. + /// An optional provider to receive progress updates. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task DisableFeatureAsync(DismSession session, string featureName, string packageName, bool removePayload, IProgress? progress, CancellationToken cancellationToken = default) + { + return DisableFeatureAsync(session, featureName, packageName, removePayload, progress, userData: null, cancellationToken); + } - Task.Factory.StartNew( - () => + /// + /// Asynchronously disables a feature in the current image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that you want to disable. To disable more than one feature, separate each feature name with a semicolon. + /// + /// Optional. The name of the parent package that the feature is a part of. + /// + /// This is an optional parameter. If no package is specified, then the default Windows® Foundation package is used. + /// + /// Specifies whether to remove the files required to enable the feature. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task DisableFeatureAsync(DismSession session, string featureName, string packageName, bool removePayload, IProgress? progress, object? userData, CancellationToken cancellationToken = default) + { + return DismUtilities.RunAsync( + static (state, progress) => { - try - { - DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); + DisableFeature(state.session, state.featureName, state.packageName, state.removePayload, progress); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - - int hresult = NativeMethods.DismDisableFeature(session, featureName, packageName, removePayload, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - - if (cancellationToken.IsCancellationRequested) - { - tcs.TrySetCanceled(cancellationToken); - } - else - { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); - } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } + return true; }, - CancellationToken.None, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + (session, featureName, packageName, removePayload), + progress, + userData, + cancellationToken); + } - return tcs.Task; + private static void DisableFeature(DismSession session, string featureName, string packageName, bool removePayload, DismProgress progress) + { + int hresult = NativeMethods.DismDisableFeature(session, featureName, packageName, removePayload, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); + + DismUtilities.ThrowIfFail(hresult, session); } -#endif internal static partial class NativeMethods { @@ -141,25 +164,32 @@ internal static partial class NativeMethods /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that you want to disable. To disable more than one feature, separate each feature name with a semicolon. - /// Optional. The name of the parent package that the feature is a part of. + /// + /// Optional. The name of the parent package that the feature is a part of. /// - /// This is an optional parameter. If no package is specified, then the default Windows® Foundation package is used. + /// This is an optional parameter. If no package is specified, then the default Windows® Foundation package is used. + /// /// A Boolean value specifying whether to remove the files required to enable the feature. /// Optional. You can set a CancelEvent for this function in order to cancel the operation in progress when signaled by the client. If the CancelEvent is received at a stage when the operation cannot be canceled, the operation will continue and return a success code. If the CancelEvent is received and the operation is canceled, the image state is unknown. You should verify the image state before continuing or discard the changes and start again. /// Optional. A pointer to a client-defined DismProgressCallback Function. /// Optional. User specified data. /// Returns S_OK on success. - /// - /// - /// HRESULT WINAPI DismDisableFeature (_In_ DismSession Session, _In_ PCWSTR FeatureName, _In_opt_ PCWSTR PackageName, _In_ BOOL RemovePayload, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); - /// - #if NET7_0_OR_GREATER + /// HRESULT WINAPI DismDisableFeature (_In_ DismSession Session, _In_ PCWSTR FeatureName, _In_opt_ PCWSTR PackageName, _In_ BOOL RemovePayload, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); +#if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismDisableFeature(DismSession session, string featureName, string packageName, [MarshalAs(UnmanagedType.Bool)] bool removePayload, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismDisableFeature(DismSession session, string featureName, string packageName, [MarshalAs(UnmanagedType.Bool)] bool removePayload, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #endif + public static extern +#endif + int DismDisableFeature( + DismSession session, + string featureName, + string packageName, + [MarshalAs(UnmanagedType.Bool)] bool removePayload, + SafeWaitHandle cancelEvent, + DismProgressCallbackNative progress, + IntPtr userData); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Dism/DismApi.EnableFeature.cs b/src/Microsoft.Dism/DismApi.EnableFeature.cs index bfb9e9b..a390e49 100644 --- a/src/Microsoft.Dism/DismApi.EnableFeature.cs +++ b/src/Microsoft.Dism/DismApi.EnableFeature.cs @@ -13,6 +13,127 @@ namespace Microsoft.Dism { public static partial class DismApi { + /// + /// Enables a feature from the specified package path. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. + /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. + /// When a failure occurs. + public static void EnableFeature(DismSession session, string featureName, bool limitAccess, bool enableAll) + { + EnableFeature(session, featureName, identifier: null, DismPackageIdentifier.None, limitAccess, enableAll, sourcePaths: null, progressCallback: null, userData: null); + } + + /// + /// Enables a feature from the specified package path. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. + /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. + /// A list of source locations to check for files needed to enable the feature. + /// When a failure occurs. + public static void EnableFeature(DismSession session, string featureName, bool limitAccess, bool enableAll, List? sourcePaths) + { + EnableFeature(session, featureName, identifier: null, DismPackageIdentifier.None, limitAccess, enableAll, sourcePaths, progressCallback: null, userData: null); + } + + /// + /// Enables a feature from the specified package path. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. + /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. + /// A list of source locations to check for files needed to enable the feature. + /// A progress callback method to invoke when progress is made. + /// When a failure occurs. + public static void EnableFeature(DismSession session, string featureName, bool limitAccess, bool enableAll, List? sourcePaths, DismProgressCallback? progressCallback) + { + EnableFeature(session, featureName, identifier: null, DismPackageIdentifier.None, limitAccess, enableAll, sourcePaths, progressCallback, userData: null); + } + + /// + /// Enables a feature from the specified package path. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. + /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. + /// A list of source locations to check for files needed to enable the feature. + /// A progress callback method to invoke when progress is made. + /// Optional user data to pass to the DismProgressCallback method. + /// When a failure occurs. + public static void EnableFeature(DismSession session, string featureName, bool limitAccess, bool enableAll, List? sourcePaths, DismProgressCallback? progressCallback, object? userData) + { + EnableFeature(session, featureName, identifier: null, DismPackageIdentifier.None, limitAccess, enableAll, sourcePaths, progressCallback, userData); + } + + /// + /// Enables a feature from the specified package path. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. + /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. + /// token to monitor for cancellation requests. The default value is . + /// When a failure occurs. + public static Task EnableFeatureAsync(DismSession session, string featureName, bool limitAccess, bool enableAll, CancellationToken cancellationToken = default) + { + return EnableFeatureAsync(session, featureName, limitAccess, enableAll, sourcePaths: null, cancellationToken); + } + + /// + /// Enables a feature from the specified package path. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. + /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. + /// A list of source locations to check for files needed to enable the feature. + /// token to monitor for cancellation requests. The default value is . + /// When a failure occurs. + public static Task EnableFeatureAsync(DismSession session, string featureName, bool limitAccess, bool enableAll, List? sourcePaths, CancellationToken cancellationToken = default) + { + return EnableFeatureAsync(session, featureName, limitAccess, enableAll, sourcePaths, progress: null, cancellationToken); + } + + /// + /// Enables a feature from the specified package path. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. + /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. + /// A list of source locations to check for files needed to enable the feature. + /// An optional provider to receive progress updates. + /// token to monitor for cancellation requests. The default value is . + /// When a failure occurs. + public static Task EnableFeatureAsync(DismSession session, string featureName, bool limitAccess, bool enableAll, List? sourcePaths, IProgress? progress, CancellationToken cancellationToken = default) + { + return EnableFeatureAsync(session, featureName, limitAccess, enableAll, sourcePaths, progress, userData: null, cancellationToken); + } + + /// + /// Enables a feature from the specified package path. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. + /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. + /// A list of source locations to check for files needed to enable the feature. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// token to monitor for cancellation requests. The default value is . + /// A that represents the asynchronous operation. + /// When a failure occurs. + public static Task EnableFeatureAsync(DismSession session, string featureName, bool limitAccess, bool enableAll, List? sourcePaths, IProgress? progress, object? userData, CancellationToken cancellationToken = default) + { + return EnableFeatureAsync(session, featureName, identifier: null, DismPackageIdentifier.None, limitAccess, enableAll, sourcePaths, progress, userData, cancellationToken); + } + /// /// Enables a feature from the specified package name. /// @@ -57,7 +178,7 @@ public static void EnableFeatureByPackageName(DismSession session, string featur /// When a failure occurs. /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static void EnableFeatureByPackageName(DismSession session, string featureName, string packageName, bool limitAccess, bool enableAll, List? sourcePaths, Microsoft.Dism.DismProgressCallback? progressCallback) + public static void EnableFeatureByPackageName(DismSession session, string featureName, string packageName, bool limitAccess, bool enableAll, List? sourcePaths, DismProgressCallback? progressCallback) { EnableFeatureByPackageName(session, featureName, packageName, limitAccess, enableAll, sourcePaths, progressCallback, null); } @@ -76,77 +197,87 @@ public static void EnableFeatureByPackageName(DismSession session, string featur /// When a failure occurs. /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static void EnableFeatureByPackageName(DismSession session, string featureName, string packageName, bool limitAccess, bool enableAll, List? sourcePaths, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) + public static void EnableFeatureByPackageName(DismSession session, string featureName, string packageName, bool limitAccess, bool enableAll, List? sourcePaths, DismProgressCallback? progressCallback, object? userData) { EnableFeature(session, featureName, packageName, DismPackageIdentifier.Name, limitAccess, enableAll, sourcePaths, progressCallback, userData); } /// - /// Enables a feature from the specified package path. + /// Enables a feature from the specified package name. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. - /// The path of the package that contains the feature. + /// The name of the package that contains the feature. /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. + /// The token to monitor for cancellation requests. The default value is . + /// A that represents the asynchronous operation. /// When a failure occurs. + /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static void EnableFeatureByPackagePath(DismSession session, string featureName, string packagePath, bool limitAccess, bool enableAll) + public static Task EnableFeatureByPackageNameAsync(DismSession session, string featureName, string packageName, bool limitAccess, bool enableAll, CancellationToken cancellationToken = default) { - EnableFeatureByPackagePath(session, featureName, packagePath, limitAccess, enableAll, sourcePaths: null, progressCallback: null); + return EnableFeatureByPackageNameAsync(session, featureName, packageName, limitAccess, enableAll, sourcePaths: null, cancellationToken); } /// - /// Enables a feature from the specified package path. + /// Enables a feature from the specified package name. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. - /// The path of the package that contains the feature. + /// The name of the package that contains the feature. /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. /// A list of source locations to check for files needed to enable the feature. + /// The token to monitor for cancellation requests. The default value is . + /// A that represents the asynchronous operation. /// When a failure occurs. + /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static void EnableFeatureByPackagePath(DismSession session, string featureName, string packagePath, bool limitAccess, bool enableAll, List? sourcePaths) + public static Task EnableFeatureByPackageNameAsync(DismSession session, string featureName, string packageName, bool limitAccess, bool enableAll, List? sourcePaths, CancellationToken cancellationToken = default) { - EnableFeatureByPackagePath(session, featureName, packagePath, limitAccess, enableAll, sourcePaths, progressCallback: null); + return EnableFeatureByPackageNameAsync(session, featureName, packageName, limitAccess, enableAll, sourcePaths, progress: null, cancellationToken); } /// - /// Enables a feature from the specified package path. + /// Enables a feature from the specified package name. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. - /// The path of the package that contains the feature. + /// The name of the package that contains the feature. /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. /// A list of source locations to check for files needed to enable the feature. - /// A progress callback method to invoke when progress is made. + /// An optional provider to receive progress updates. + /// token to monitor for cancellation requests. The default value is . + /// A that represents the asynchronous operation. /// When a failure occurs. /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static void EnableFeatureByPackagePath(DismSession session, string featureName, string packagePath, bool limitAccess, bool enableAll, List? sourcePaths, Microsoft.Dism.DismProgressCallback? progressCallback) + public static Task EnableFeatureByPackageNameAsync(DismSession session, string featureName, string packageName, bool limitAccess, bool enableAll, List? sourcePaths, IProgress? progress, CancellationToken cancellationToken = default) { - EnableFeatureByPackagePath(session, featureName, packagePath, limitAccess, enableAll, sourcePaths, progressCallback, userData: null); + return EnableFeatureByPackageNameAsync(session, featureName, packageName, limitAccess, enableAll, sourcePaths, progress, userData: null, cancellationToken); } /// - /// Enables a feature from the specified package path. + /// Enables a feature from the specified package name. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. - /// The path of the package that contains the feature. + /// The name of the package that contains the feature. /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. /// A list of source locations to check for files needed to enable the feature. - /// A progress callback method to invoke when progress is made. - /// Optional user data to pass to the DismProgressCallback method. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// token to monitor for cancellation requests. The default value is . + /// A that represents the asynchronous operation. /// When a failure occurs. /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static void EnableFeatureByPackagePath(DismSession session, string featureName, string packagePath, bool limitAccess, bool enableAll, List? sourcePaths, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) + public static Task EnableFeatureByPackageNameAsync(DismSession session, string featureName, string packageName, bool limitAccess, bool enableAll, List? sourcePaths, IProgress? progress, object? userData, CancellationToken cancellationToken = default) { - EnableFeature(session, featureName, packagePath, DismPackageIdentifier.Path, limitAccess, enableAll, sourcePaths, progressCallback, userData); + return EnableFeatureAsync(session, featureName, packageName, DismPackageIdentifier.Name, limitAccess, enableAll, sourcePaths, progress, userData, cancellationToken); } /// @@ -154,12 +285,14 @@ public static void EnableFeatureByPackagePath(DismSession session, string featur /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// The path of the package that contains the feature. /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. /// When a failure occurs. - public static void EnableFeature(DismSession session, string featureName, bool limitAccess, bool enableAll) + /// When the operation requires a reboot to complete. + public static void EnableFeatureByPackagePath(DismSession session, string featureName, string packagePath, bool limitAccess, bool enableAll) { - EnableFeature(session, featureName, identifier: null, DismPackageIdentifier.None, limitAccess, enableAll, sourcePaths: null, progressCallback: null, userData: null); + EnableFeatureByPackagePath(session, featureName, packagePath, limitAccess, enableAll, sourcePaths: null, progressCallback: null); } /// @@ -167,13 +300,15 @@ public static void EnableFeature(DismSession session, string featureName, bool l /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// The path of the package that contains the feature. /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. /// A list of source locations to check for files needed to enable the feature. /// When a failure occurs. - public static void EnableFeature(DismSession session, string featureName, bool limitAccess, bool enableAll, List? sourcePaths) + /// When the operation requires a reboot to complete. + public static void EnableFeatureByPackagePath(DismSession session, string featureName, string packagePath, bool limitAccess, bool enableAll, List? sourcePaths) { - EnableFeature(session, featureName, identifier: null, DismPackageIdentifier.None, limitAccess, enableAll, sourcePaths, progressCallback: null, userData: null); + EnableFeatureByPackagePath(session, featureName, packagePath, limitAccess, enableAll, sourcePaths, progressCallback: null); } /// @@ -181,14 +316,17 @@ public static void EnableFeature(DismSession session, string featureName, bool l /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// The path of the package that contains the feature. /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. /// A list of source locations to check for files needed to enable the feature. /// A progress callback method to invoke when progress is made. /// When a failure occurs. - public static void EnableFeature(DismSession session, string featureName, bool limitAccess, bool enableAll, List? sourcePaths, Microsoft.Dism.DismProgressCallback? progressCallback) + /// When the user requested the operation be canceled. + /// When the operation requires a reboot to complete. + public static void EnableFeatureByPackagePath(DismSession session, string featureName, string packagePath, bool limitAccess, bool enableAll, List? sourcePaths, DismProgressCallback? progressCallback) { - EnableFeature(session, featureName, identifier: null, DismPackageIdentifier.None, limitAccess, enableAll, sourcePaths, progressCallback, userData: null); + EnableFeatureByPackagePath(session, featureName, packagePath, limitAccess, enableAll, sourcePaths, progressCallback, userData: null); } /// @@ -196,59 +334,59 @@ public static void EnableFeature(DismSession session, string featureName, bool l /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// The path of the package that contains the feature. /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. /// A list of source locations to check for files needed to enable the feature. /// A progress callback method to invoke when progress is made. /// Optional user data to pass to the DismProgressCallback method. /// When a failure occurs. - public static void EnableFeature(DismSession session, string featureName, bool limitAccess, bool enableAll, List? sourcePaths, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) + /// When the user requested the operation be canceled. + /// When the operation requires a reboot to complete. + public static void EnableFeatureByPackagePath(DismSession session, string featureName, string packagePath, bool limitAccess, bool enableAll, List? sourcePaths, DismProgressCallback? progressCallback, object? userData) { - EnableFeature(session, featureName, identifier: null, DismPackageIdentifier.None, limitAccess, enableAll, sourcePaths, progressCallback, userData); + EnableFeature(session, featureName, packagePath, DismPackageIdentifier.Path, limitAccess, enableAll, sourcePaths, progressCallback, userData); } -#if !NET40 /// - /// Asynchronously enables a feature from the default package. + /// Enables a feature from the specified package path. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// The path of the package that contains the feature. /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. - /// A list of source locations to check for files needed to enable the feature. - /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. - /// A representing the asynchronous operation. + /// token to monitor for cancellation requests. The default value is . + /// A that represents the asynchronous operation. /// When a failure occurs. - /// When the operation is canceled. + /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static Task EnableFeatureAsync(DismSession session, string featureName, bool limitAccess, bool enableAll, List? sourcePaths = null, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task EnableFeatureByPackagePathAsync(DismSession session, string featureName, string packagePath, bool limitAccess, bool enableAll, CancellationToken cancellationToken = default) { - return EnableFeatureAsync(session, featureName, null, DismPackageIdentifier.None, limitAccess, enableAll, sourcePaths, progress, cancellationToken); + return EnableFeatureByPackagePathAsync(session, featureName, packagePath, limitAccess, enableAll, sourcePaths: null, cancellationToken); } /// - /// Asynchronously enables a feature from the specified package name. + /// Enables a feature from the specified package path. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. - /// The name of the package that contains the feature. + /// The path of the package that contains the feature. /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. /// A list of source locations to check for files needed to enable the feature. - /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. - /// A representing the asynchronous operation. + /// token to monitor for cancellation requests. The default value is . + /// A that represents the asynchronous operation. /// When a failure occurs. - /// When the operation is canceled. + /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static Task EnableFeatureByPackageNameAsync(DismSession session, string featureName, string packageName, bool limitAccess, bool enableAll, List? sourcePaths = null, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task EnableFeatureByPackagePathAsync(DismSession session, string featureName, string packagePath, bool limitAccess, bool enableAll, List? sourcePaths, CancellationToken cancellationToken = default) { - return EnableFeatureAsync(session, featureName, packageName, DismPackageIdentifier.Name, limitAccess, enableAll, sourcePaths, progress, cancellationToken); + return EnableFeatureByPackagePathAsync(session, featureName, packagePath, limitAccess, enableAll, sourcePaths, progress: null, cancellationToken); } /// - /// Asynchronously enables a feature from the specified package path. + /// Enables a feature from the specified package path. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. @@ -256,91 +394,43 @@ public static Task EnableFeatureByPackageNameAsync(DismSession session, string f /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. /// A list of source locations to check for files needed to enable the feature. - /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. - /// A representing the asynchronous operation. + /// An optional provider to receive progress updates. + /// token to monitor for cancellation requests. The default value is . + /// A that represents the asynchronous operation. /// When a failure occurs. - /// When the operation is canceled. + /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static Task EnableFeatureByPackagePathAsync(DismSession session, string featureName, string packagePath, bool limitAccess, bool enableAll, List? sourcePaths = null, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task EnableFeatureByPackagePathAsync(DismSession session, string featureName, string packagePath, bool limitAccess, bool enableAll, List? sourcePaths, IProgress? progress, CancellationToken cancellationToken = default) { - return EnableFeatureAsync(session, featureName, packagePath, DismPackageIdentifier.Path, limitAccess, enableAll, sourcePaths, progress, cancellationToken); - } - - /// - /// Asynchronously enables a feature in an image. - /// - private static Task EnableFeatureAsync(DismSession session, string featureName, string? identifier, DismPackageIdentifier packageIdentifier, bool limitAccess, bool enableAll, List? sourcePaths, IProgress? progress, CancellationToken cancellationToken) - { - TaskCompletionSource tcs = new(); - - CancellationTokenRegistration ctsRegistration = default; - - Task.Factory.StartNew( - () => - { - try - { - string[] sourcePathsArray = sourcePaths?.ToArray() ?? []; - - DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); - - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - - int hresult = NativeMethods.DismEnableFeature(session, featureName, identifier, identifier == null ? DismPackageIdentifier.None : packageIdentifier, limitAccess, sourcePathsArray, (uint)sourcePathsArray.Length, enableAll, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - - if (cancellationToken.IsCancellationRequested) - { - tcs.TrySetCanceled(cancellationToken); - } - else - { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); - } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - CancellationToken.None, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); - - return tcs.Task; + return EnableFeatureByPackagePathAsync(session, featureName, packagePath, limitAccess, enableAll, sourcePaths, progress, userData: null, cancellationToken); } -#endif /// /// Enables a feature from the specified package path. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. - /// A package name or absolute path. - /// A DismPackageIdentifier value. + /// The path of the package that contains the feature. /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. /// A list of source locations to check for files needed to enable the feature. - /// A progress callback method to invoke when progress is made. - /// Optional user data to pass to the DismProgressCallback method. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// token to monitor for cancellation requests. The default value is . + /// A that represents the asynchronous operation. /// When a failure occurs. - private static void EnableFeature(DismSession session, string featureName, string? identifier, DismPackageIdentifier packageIdentifier, bool limitAccess, bool enableAll, List? sourcePaths, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) + /// When the user requested the operation be canceled. + /// When the operation requires a reboot to complete. + public static Task EnableFeatureByPackagePathAsync(DismSession session, string featureName, string packagePath, bool limitAccess, bool enableAll, List? sourcePaths, IProgress? progress, object? userData, CancellationToken cancellationToken = default) + { + return EnableFeatureAsync(session, featureName, packagePath, DismPackageIdentifier.Path, limitAccess, enableAll, sourcePaths, progress, userData, cancellationToken); + } + + private static void EnableFeature(DismSession session, string featureName, string? identifier, DismPackageIdentifier packageIdentifier, bool limitAccess, bool enableAll, List? sourcePaths, DismProgress progress) { // Get the list of source paths as an array string[] sourcePathsArray = sourcePaths?.ToArray() ?? []; - // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new(progressCallback, userData); - int hresult = NativeMethods.DismEnableFeature( session: session, featureName: featureName, @@ -357,6 +447,41 @@ private static void EnableFeature(DismSession session, string featureName, strin DismUtilities.ThrowIfFail(hresult, session); } + /// + /// Enables a feature from the specified package path. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the feature that is being enabled. To enable more than one feature, separate each feature name with a semicolon. + /// A package name or absolute path. + /// A DismPackageIdentifier value. + /// Specifies whether Windows Update (WU) should be contacted as a source location for downloading files if none are found in other specified locations. Before checking WU, DISM will check for the files in the SourcePaths provided and in any locations specified in the registry by group policy. If the files required to enable the feature are still present on the computer, this flag is ignored. + /// Specifies whether to enable all dependencies of the feature. If the specified feature or any one of its dependencies cannot be enabled, none of them will be changed from their existing state. + /// A list of source locations to check for files needed to enable the feature. + /// A progress callback method to invoke when progress is made. + /// Optional user data to pass to the DismProgressCallback method. + /// When a failure occurs. + private static void EnableFeature(DismSession session, string featureName, string? identifier, DismPackageIdentifier packageIdentifier, bool limitAccess, bool enableAll, List? sourcePaths, DismProgressCallback? progressCallback, object? userData) + { + using DismProgress progress = new(progressCallback, userData); + + EnableFeature(session, featureName, identifier, packageIdentifier, limitAccess, enableAll, sourcePaths, progress); + } + + private static Task EnableFeatureAsync(DismSession session, string featureName, string? identifier, DismPackageIdentifier packageIdentifier, bool limitAccess, bool enableAll, List? sourcePaths, IProgress? progress, object? userData, CancellationToken cancellationToken = default) + { + return DismUtilities.RunAsync( + static (state, progress) => + { + EnableFeature(state.session, state.featureName, state.identifier, state.packageIdentifier, state.limitAccess, state.enableAll, state.sourcePaths, progress); + + return true; + }, + (session, featureName, identifier, packageIdentifier, limitAccess, enableAll, sourcePaths), + progress, + userData, + cancellationToken); + } + internal static partial class NativeMethods { /// @@ -374,20 +499,36 @@ internal static partial class NativeMethods /// Optional. A pointer to a client-defined DismProgressCallback Function. /// Optional. User defined custom data. /// Returns S_OK on success. - /// If the feature is present in the foundation package, you do not have to specify any package information. If the feature is in an optional package or feature pack that has already been installed in the image, specify a package name in the Identifier parameter and specify DismPackageName as the PackageIdentifier.If the feature cannot be enabled due to the parent feature not being enabled, a special error code will be returned. You can use EnableAll to enable the parent features when you enable the specified features, or you can use the DismGetFeatureParent Function to enumerate the parent features and enable them first. + /// + /// If the feature is present in the foundation package, you do not have to specify any package information. If the feature is in an optional package or feature pack that has already been installed in the image, specify a package name in the Identifier parameter and specify DismPackageName as the PackageIdentifier.If the feature cannot be enabled due to the parent feature not being enabled, a special error code will be returned. You can use EnableAll to enable the parent features when you enable the specified features, or you can use the DismGetFeatureParent Function to enumerate the parent features and enable them first. /// /// If the feature to be enabled is not a component of the foundation package, you must add the parent optional package with the DismAddPackage Function before you enable the feature. Do not you specify a path to a .cab file of an optional package that has not been added to the image in the Identifier parameter. If you specify a package that has not been added, and you specify DismPackagePath as the PackageIdentifier, the function will complete successfully but the feature will not be enabled. /// - /// - /// HRESULT WINAPI DismEnableFeature (_In_ DismSession Session, _In_ PCWSTR FeatureName, _In_opt_ PCWSTR Identifier, _In_opt_ DismPackageIdentifier PackageIdentifier, _In_ BOOL LimitAccess, _In_reads_opt_(SourcePathCount) PCWSTR* SourcePaths, _In_opt_ UINT SourcePathCount, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); + /// HRESULT WINAPI DismEnableFeature (_In_ DismSession Session, _In_ PCWSTR FeatureName, _In_opt_ PCWSTR Identifier, _In_opt_ DismPackageIdentifier PackageIdentifier, _In_ BOOL LimitAccess, _In_reads_opt_(SourcePathCount) PCWSTR* SourcePaths, _In_opt_ UINT SourcePathCount, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); /// - #if NET7_0_OR_GREATER +#if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismEnableFeature(DismSession session, string featureName, string? identifier, DismPackageIdentifier packageIdentifier, [MarshalAs(UnmanagedType.Bool)] bool limitAccess, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 6)] string[] sourcePaths, UInt32 sourcePathCount, [MarshalAs(UnmanagedType.Bool)] bool enableAll, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #else + public static partial +#else + [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismEnableFeature(DismSession session, string featureName, string? identifier, DismPackageIdentifier packageIdentifier, [MarshalAs(UnmanagedType.Bool)] bool limitAccess, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 6)] string[] sourcePaths, UInt32 sourcePathCount, [MarshalAs(UnmanagedType.Bool)] bool enableAll, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #endif + public static extern +#endif + int DismEnableFeature( + DismSession session, + string featureName, + string? identifier, + DismPackageIdentifier packageIdentifier, + [MarshalAs(UnmanagedType.Bool)] + bool limitAccess, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 6)] + string[] sourcePaths, + UInt32 sourcePathCount, + [MarshalAs(UnmanagedType.Bool)] + bool enableAll, + SafeWaitHandle cancelEvent, + DismProgressCallbackNative progress, + IntPtr userData); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Dism/DismApi.GetCapabilities.cs b/src/Microsoft.Dism/DismApi.GetCapabilities.cs index f86c0e8..e619e76 100644 --- a/src/Microsoft.Dism/DismApi.GetCapabilities.cs +++ b/src/Microsoft.Dism/DismApi.GetCapabilities.cs @@ -42,11 +42,15 @@ internal static partial class NativeMethods /// Returns S_OK on success. #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismGetCapabilities(DismSession session, out IntPtr capability, out UInt32 count); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismGetCapabilities(DismSession session, out IntPtr capability, out UInt32 count); - #endif + public static extern +#endif + int DismGetCapabilities( + DismSession session, + out IntPtr capability, + out UInt32 count); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetCapabilityInfo.cs b/src/Microsoft.Dism/DismApi.GetCapabilityInfo.cs index a1b7ebb..f48fc8e 100644 --- a/src/Microsoft.Dism/DismApi.GetCapabilityInfo.cs +++ b/src/Microsoft.Dism/DismApi.GetCapabilityInfo.cs @@ -45,11 +45,15 @@ internal static partial class NativeMethods /// Returns S_OK on success. #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismGetCapabilityInfo(DismSession session, string name, out IntPtr info); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismGetCapabilityInfo(DismSession session, string name, out IntPtr info); - #endif + public static extern +#endif + int DismGetCapabilityInfo( + DismSession session, + string name, + out IntPtr info); } } } diff --git a/src/Microsoft.Dism/DismApi.GetCurrentEdition.cs b/src/Microsoft.Dism/DismApi.GetCurrentEdition.cs index 7915c3f..4308932 100644 --- a/src/Microsoft.Dism/DismApi.GetCurrentEdition.cs +++ b/src/Microsoft.Dism/DismApi.GetCurrentEdition.cs @@ -43,11 +43,14 @@ internal static partial class NativeMethods /// Returns S_OK on success. #if NET7_0_OR_GREATER [LibraryImport(DismDllName, EntryPoint = "_DismGetCurrentEdition")] - public static partial int DismGetCurrentEdition(DismSession session, out IntPtr editionId); - #else + public static partial +#else [DllImport(DismDllName, EntryPoint = "_DismGetCurrentEdition")] - public static extern int DismGetCurrentEdition(DismSession session, out IntPtr editionId); - #endif + public static extern +#endif + int DismGetCurrentEdition( + DismSession session, + out IntPtr editionId); } } } diff --git a/src/Microsoft.Dism/DismApi.GetDriverInfo.cs b/src/Microsoft.Dism/DismApi.GetDriverInfo.cs index 042eb0f..c58d8c0 100644 --- a/src/Microsoft.Dism/DismApi.GetDriverInfo.cs +++ b/src/Microsoft.Dism/DismApi.GetDriverInfo.cs @@ -72,11 +72,17 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismGetDriverInfo(DismSession session, string driverPath, out IntPtr driver, out UInt32 count, out IntPtr driverPackage); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismGetDriverInfo(DismSession session, string driverPath, out IntPtr driver, out UInt32 count, out IntPtr driverPackage); - #endif + public static extern +#endif + int DismGetDriverInfo( + DismSession session, + string driverPath, + out IntPtr driver, + out UInt32 count, + out IntPtr driverPackage); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetDrivers.cs b/src/Microsoft.Dism/DismApi.GetDrivers.cs index 92dcd37..8294013 100644 --- a/src/Microsoft.Dism/DismApi.GetDrivers.cs +++ b/src/Microsoft.Dism/DismApi.GetDrivers.cs @@ -13,7 +13,7 @@ public static partial class DismApi /// Gets the drivers in an image. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. - /// true or false to specify to retrieve all drivers or just out-of-box drivers. + /// to retrieve all drivers or to retrieve just out-of-box drivers. /// A object containing a collection of objects. /// When a failure occurs. public static DismDriverPackageCollection GetDrivers(DismSession session, bool allDrivers) @@ -49,11 +49,16 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismGetDrivers(DismSession Session, [MarshalAs(UnmanagedType.Bool)] bool AllDrivers, out IntPtr DriverPackage, out UInt32 Count); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismGetDrivers(DismSession Session, [MarshalAs(UnmanagedType.Bool)] bool AllDrivers, out IntPtr DriverPackage, out UInt32 Count); - #endif + public static extern +#endif + int DismGetDrivers( + DismSession Session, + [MarshalAs(UnmanagedType.Bool)] bool AllDrivers, + out IntPtr DriverPackage, + out UInt32 Count); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetFeatureInfo.cs b/src/Microsoft.Dism/DismApi.GetFeatureInfo.cs index 2b9a4f7..4007c5f 100644 --- a/src/Microsoft.Dism/DismApi.GetFeatureInfo.cs +++ b/src/Microsoft.Dism/DismApi.GetFeatureInfo.cs @@ -91,11 +91,17 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismGetFeatureInfo(DismSession session, string featureName, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr featureInfo); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismGetFeatureInfo(DismSession session, string featureName, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr featureInfo); - #endif + public static extern +#endif + int DismGetFeatureInfo( + DismSession session, + string featureName, + string identifier, + DismPackageIdentifier packageIdentifier, + out IntPtr featureInfo); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetFeatureParent.cs b/src/Microsoft.Dism/DismApi.GetFeatureParent.cs index e6a9e34..9f35720 100644 --- a/src/Microsoft.Dism/DismApi.GetFeatureParent.cs +++ b/src/Microsoft.Dism/DismApi.GetFeatureParent.cs @@ -79,11 +79,18 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismGetFeatureParent(DismSession session, string featureName, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr feature, out UInt32 count); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismGetFeatureParent(DismSession session, string featureName, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr feature, out UInt32 count); - #endif + public static extern +#endif + int DismGetFeatureParent( + DismSession session, + string featureName, + string identifier, + DismPackageIdentifier packageIdentifier, + out IntPtr feature, + out UInt32 count); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetFeatures.cs b/src/Microsoft.Dism/DismApi.GetFeatures.cs index a2e59be..3a3eb34 100644 --- a/src/Microsoft.Dism/DismApi.GetFeatures.cs +++ b/src/Microsoft.Dism/DismApi.GetFeatures.cs @@ -85,11 +85,17 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismGetFeatures(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr feature, out UInt32 count); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismGetFeatures(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr feature, out UInt32 count); - #endif + public static extern +#endif + int DismGetFeatures( + DismSession session, + string identifier, + DismPackageIdentifier packageIdentifier, + out IntPtr feature, + out UInt32 count); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetImageInfo.cs b/src/Microsoft.Dism/DismApi.GetImageInfo.cs index d8ce28b..89bb25c 100644 --- a/src/Microsoft.Dism/DismApi.GetImageInfo.cs +++ b/src/Microsoft.Dism/DismApi.GetImageInfo.cs @@ -51,11 +51,15 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismGetImageInfo(string imageFilePath, out IntPtr imageInfo, out UInt32 count); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismGetImageInfo(string imageFilePath, out IntPtr imageInfo, out UInt32 count); - #endif + public static extern +#endif + int DismGetImageInfo( + string imageFilePath, + out IntPtr imageInfo, + out UInt32 count); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetLastErrorMessage.cs b/src/Microsoft.Dism/DismApi.GetLastErrorMessage.cs index 0881fb7..71c63ed 100644 --- a/src/Microsoft.Dism/DismApi.GetLastErrorMessage.cs +++ b/src/Microsoft.Dism/DismApi.GetLastErrorMessage.cs @@ -64,11 +64,13 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismGetLastErrorMessage(out IntPtr errorMessage); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismGetLastErrorMessage(out IntPtr errorMessage); - #endif + public static extern +#endif + int DismGetLastErrorMessage( + out IntPtr errorMessage); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetMountedImages.cs b/src/Microsoft.Dism/DismApi.GetMountedImages.cs index 7e97e41..8306a54 100644 --- a/src/Microsoft.Dism/DismApi.GetMountedImages.cs +++ b/src/Microsoft.Dism/DismApi.GetMountedImages.cs @@ -50,11 +50,14 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismGetMountedImageInfo(out IntPtr mountedImageInfo, out UInt32 count); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismGetMountedImageInfo(out IntPtr mountedImageInfo, out UInt32 count); - #endif + public static extern +#endif + int DismGetMountedImageInfo( + out IntPtr mountedImageInfo, + out UInt32 count); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetPackageInfo.cs b/src/Microsoft.Dism/DismApi.GetPackageInfo.cs index 65d3eaa..90f66d5 100644 --- a/src/Microsoft.Dism/DismApi.GetPackageInfo.cs +++ b/src/Microsoft.Dism/DismApi.GetPackageInfo.cs @@ -75,11 +75,16 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismGetPackageInfo(DismSession dismSession, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr packageInfo); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismGetPackageInfo(DismSession dismSession, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr packageInfo); - #endif + public static extern +#endif + int DismGetPackageInfo( + DismSession dismSession, + string identifier, + DismPackageIdentifier packageIdentifier, + out IntPtr packageInfo); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetPackageInfoEx.cs b/src/Microsoft.Dism/DismApi.GetPackageInfoEx.cs index 29c74a5..58686e3 100644 --- a/src/Microsoft.Dism/DismApi.GetPackageInfoEx.cs +++ b/src/Microsoft.Dism/DismApi.GetPackageInfoEx.cs @@ -73,11 +73,16 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismGetPackageInfoEx(DismSession dismSession, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr packageInfoEx); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismGetPackageInfoEx(DismSession dismSession, string identifier, DismPackageIdentifier packageIdentifier, out IntPtr packageInfoEx); - #endif + public static extern +#endif + int DismGetPackageInfoEx( + DismSession dismSession, + string identifier, + DismPackageIdentifier packageIdentifier, + out IntPtr packageInfoEx); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetPackages.cs b/src/Microsoft.Dism/DismApi.GetPackages.cs index ca23d32..e822e46 100644 --- a/src/Microsoft.Dism/DismApi.GetPackages.cs +++ b/src/Microsoft.Dism/DismApi.GetPackages.cs @@ -50,11 +50,15 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismGetPackages(DismSession dismSession, out IntPtr packageInfo, out UInt32 count); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismGetPackages(DismSession dismSession, out IntPtr packageInfo, out UInt32 count); - #endif + public static extern +#endif + int DismGetPackages( + DismSession dismSession, + out IntPtr packageInfo, + out UInt32 count); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetProductKeyInfo.cs b/src/Microsoft.Dism/DismApi.GetProductKeyInfo.cs index ba30e85..097f379 100644 --- a/src/Microsoft.Dism/DismApi.GetProductKeyInfo.cs +++ b/src/Microsoft.Dism/DismApi.GetProductKeyInfo.cs @@ -48,11 +48,16 @@ internal static partial class NativeMethods /// Returns S_OK on success. #if NET7_0_OR_GREATER [LibraryImport(DismDllName, EntryPoint = "_DismGetProductKeyInfo", StringMarshalling = DismStringMarshalling)] - public static partial int DismGetProductKeyInfo(DismSession session, string productKey, out IntPtr editionIdPtr, out IntPtr channelPtr); - #else + public static partial +#else [DllImport(DismDllName, EntryPoint = "_DismGetProductKeyInfo", CharSet = DismCharacterSet)] - public static extern int DismGetProductKeyInfo(DismSession session, string productKey, out IntPtr editionIdPtr, out IntPtr channelPtr); - #endif + public static extern +#endif + int DismGetProductKeyInfo( + DismSession session, + string productKey, + out IntPtr editionIdPtr, + out IntPtr channelPtr); } } } diff --git a/src/Microsoft.Dism/DismApi.GetProvisionedAppxPackages.cs b/src/Microsoft.Dism/DismApi.GetProvisionedAppxPackages.cs index d3a4b4e..d3f5f60 100644 --- a/src/Microsoft.Dism/DismApi.GetProvisionedAppxPackages.cs +++ b/src/Microsoft.Dism/DismApi.GetProvisionedAppxPackages.cs @@ -43,11 +43,15 @@ internal static partial class NativeMethods /// Returns S_OK on success. #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int _DismGetProvisionedAppxPackages(DismSession session, out IntPtr packageBufPtr, out UInt32 packageCount); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int _DismGetProvisionedAppxPackages(DismSession session, out IntPtr packageBufPtr, out UInt32 packageCount); - #endif + public static extern +#endif + int _DismGetProvisionedAppxPackages( + DismSession session, + out IntPtr packageBufPtr, + out UInt32 packageCount); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.GetRegistryMountPoint.cs b/src/Microsoft.Dism/DismApi.GetRegistryMountPoint.cs index b6b7d7b..5534a4c 100644 --- a/src/Microsoft.Dism/DismApi.GetRegistryMountPoint.cs +++ b/src/Microsoft.Dism/DismApi.GetRegistryMountPoint.cs @@ -46,11 +46,15 @@ internal static partial class NativeMethods /// Returns S_OK on success. #if NET7_0_OR_GREATER [LibraryImport(DismDllName, EntryPoint = "_DismGetRegistryMountPoint")] - public static partial int DismGetRegistryMountPoint(DismSession session, DismRegistryHive registryHive, out IntPtr registryMountPointPtr); - #else + public static partial +#else [DllImport(DismDllName, EntryPoint = "_DismGetRegistryMountPoint")] - public static extern int DismGetRegistryMountPoint(DismSession session, DismRegistryHive registryHive, out IntPtr registryMountPointPtr); - #endif + public static extern +#endif + int DismGetRegistryMountPoint( + DismSession session, + DismRegistryHive registryHive, + out IntPtr registryMountPointPtr); } } } diff --git a/src/Microsoft.Dism/DismApi.GetTargetEditions.cs b/src/Microsoft.Dism/DismApi.GetTargetEditions.cs index 4111f77..4b8ac27 100644 --- a/src/Microsoft.Dism/DismApi.GetTargetEditions.cs +++ b/src/Microsoft.Dism/DismApi.GetTargetEditions.cs @@ -42,11 +42,15 @@ internal static partial class NativeMethods /// Returns S_OK on success. #if NET7_0_OR_GREATER [LibraryImport(DismDllName, EntryPoint = "_DismGetTargetEditions")] - public static partial int DismGetTargetEditions(DismSession session, out IntPtr editionIds, out uint count); - #else + public static partial +#else [DllImport(DismDllName, EntryPoint = "_DismGetTargetEditions")] - public static extern int DismGetTargetEditions(DismSession session, out IntPtr editionIds, out uint count); - #endif + public static extern +#endif + int DismGetTargetEditions( + DismSession session, + out IntPtr editionIds, + out uint count); } } } diff --git a/src/Microsoft.Dism/DismApi.Initialize.cs b/src/Microsoft.Dism/DismApi.Initialize.cs index 4bea113..84b0786 100644 --- a/src/Microsoft.Dism/DismApi.Initialize.cs +++ b/src/Microsoft.Dism/DismApi.Initialize.cs @@ -81,11 +81,15 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismInitialize(DismLogLevel logLevel, string? logFilePath, string? scratchDirectory); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismInitialize(DismLogLevel logLevel, string? logFilePath, string? scratchDirectory); - #endif + public static extern +#endif + int DismInitialize( + DismLogLevel logLevel, + string? logFilePath, + string? scratchDirectory); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.MountImage.cs b/src/Microsoft.Dism/DismApi.MountImage.cs index 5504873..1566cd6 100644 --- a/src/Microsoft.Dism/DismApi.MountImage.cs +++ b/src/Microsoft.Dism/DismApi.MountImage.cs @@ -61,7 +61,7 @@ public static void MountImage(string imageFilePath, string mountPath, int imageI /// A progress callback method to invoke when progress is made. /// When a failure occurs. /// When the user requested the operation be canceled. - public static void MountImage(string imageFilePath, string mountPath, int imageIndex, bool readOnly, Dism.DismProgressCallback? progressCallback) + public static void MountImage(string imageFilePath, string mountPath, int imageIndex, bool readOnly, DismProgressCallback? progressCallback) { MountImage(imageFilePath, mountPath, imageIndex, readOnly, DismMountImageOptions.None, progressCallback); } @@ -77,7 +77,7 @@ public static void MountImage(string imageFilePath, string mountPath, int imageI /// A progress callback method to invoke when progress is made. /// When a failure occurs. /// When the user requested the operation be canceled. - public static void MountImage(string imageFilePath, string mountPath, int imageIndex, bool readOnly, DismMountImageOptions options, Dism.DismProgressCallback? progressCallback) + public static void MountImage(string imageFilePath, string mountPath, int imageIndex, bool readOnly, DismMountImageOptions options, DismProgressCallback? progressCallback) { MountImage(imageFilePath, mountPath, imageIndex, readOnly, options, progressCallback, userData: null); } @@ -93,7 +93,7 @@ public static void MountImage(string imageFilePath, string mountPath, int imageI /// Optional user data to pass to the DismProgressCallback method. /// When a failure occurs. /// When the user requested the operation be canceled. - public static void MountImage(string imageFilePath, string mountPath, int imageIndex, bool readOnly, Dism.DismProgressCallback? progressCallback, object? userData) + public static void MountImage(string imageFilePath, string mountPath, int imageIndex, bool readOnly, DismProgressCallback? progressCallback, object? userData) { MountImage(imageFilePath, mountPath, imageIndex, readOnly, DismMountImageOptions.None, progressCallback, userData); } @@ -110,7 +110,7 @@ public static void MountImage(string imageFilePath, string mountPath, int imageI /// Optional user data to pass to the DismProgressCallback method. /// When a failure occurs. /// When the user requested the operation be canceled. - public static void MountImage(string imageFilePath, string mountPath, int imageIndex, bool readOnly, DismMountImageOptions options, Dism.DismProgressCallback? progressCallback, object? userData) + public static void MountImage(string imageFilePath, string mountPath, int imageIndex, bool readOnly, DismMountImageOptions options, DismProgressCallback? progressCallback, object? userData) { MountImage(imageFilePath, mountPath, imageIndex, imageName: null, DismImageIdentifier.ImageIndex, readOnly, options, progressCallback, userData); } @@ -164,7 +164,7 @@ public static void MountImage(string imageFilePath, string mountPath, string? im /// A progress callback method to invoke when progress is made. /// When a failure occurs. /// When the user requested the operation be canceled. - public static void MountImage(string imageFilePath, string mountPath, string? imageName, bool readOnly, Dism.DismProgressCallback progressCallback) + public static void MountImage(string imageFilePath, string mountPath, string? imageName, bool readOnly, DismProgressCallback progressCallback) { MountImage(imageFilePath, mountPath, imageName, readOnly, DismMountImageOptions.None, progressCallback); } @@ -180,7 +180,7 @@ public static void MountImage(string imageFilePath, string mountPath, string? im /// A progress callback method to invoke when progress is made. /// When a failure occurs. /// When the user requested the operation be canceled. - public static void MountImage(string imageFilePath, string mountPath, string? imageName, bool readOnly, DismMountImageOptions options, Dism.DismProgressCallback? progressCallback) + public static void MountImage(string imageFilePath, string mountPath, string? imageName, bool readOnly, DismMountImageOptions options, DismProgressCallback? progressCallback) { MountImage(imageFilePath, mountPath, imageName, readOnly, options, progressCallback, null); } @@ -196,7 +196,7 @@ public static void MountImage(string imageFilePath, string mountPath, string? im /// Optional user data to pass to the DismProgressCallback method. /// When a failure occurs. /// When the user requested the operation be canceled. - public static void MountImage(string imageFilePath, string mountPath, string? imageName, bool readOnly, Dism.DismProgressCallback? progressCallback, object? userData) + public static void MountImage(string imageFilePath, string mountPath, string? imageName, bool readOnly, DismProgressCallback? progressCallback, object? userData) { MountImage(imageFilePath, mountPath, imageName, readOnly, DismMountImageOptions.None, progressCallback, userData); } @@ -213,100 +213,166 @@ public static void MountImage(string imageFilePath, string mountPath, string? im /// Optional user data to pass to the DismProgressCallback method. /// When a failure occurs. /// When the user requested the operation be canceled. - public static void MountImage(string imageFilePath, string mountPath, string? imageName, bool readOnly, DismMountImageOptions options, Dism.DismProgressCallback? progressCallback, object? userData) + public static void MountImage(string imageFilePath, string mountPath, string? imageName, bool readOnly, DismMountImageOptions options, DismProgressCallback? progressCallback, object? userData) { MountImage(imageFilePath, mountPath, 0, imageName, DismImageIdentifier.ImageName, readOnly, options, progressCallback, userData); } -#if !NET40 /// - /// Asynchronously mounts a WIM or VHD image file to a specified location using an image index. + /// Asynchronously mounts a WIM or VHD image file to a specified location. + /// + /// The path to the WIM or VHD file on the local computer. A .wim, .vhd, or .vhdx file name extension is required. + /// The path of the location where the image should be mounted. This mount path must already exist on the computer. The Windows image in a .wim, .vhd, or .vhdx file can be mounted to an empty folder on an NTFS formatted drive. A Windows image in a .vhd or .vhdx file can also be mounted to an unassigned drive letter. You cannot mount an image to the root of the existing drive. + /// The index of the image in the WIM file that you want to mount. For a VHD file, you must specify an index of 1. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + public static Task MountImageAsync(string imageFilePath, string mountPath, int imageIndex, CancellationToken cancellationToken = default) + { + return MountImageAsync(imageFilePath, mountPath, imageIndex, readOnly: false, cancellationToken); + } + + /// + /// Asynchronously mounts a WIM or VHD image file to a specified location. + /// + /// The path to the WIM or VHD file on the local computer. A .wim, .vhd, or .vhdx file name extension is required. + /// The path of the location where the image should be mounted. This mount path must already exist on the computer. The Windows image in a .wim, .vhd, or .vhdx file can be mounted to an empty folder on an NTFS formatted drive. A Windows image in a .vhd or .vhdx file can also be mounted to an unassigned drive letter. You cannot mount an image to the root of the existing drive. + /// The index of the image in the WIM file that you want to mount. For a VHD file, you must specify an index of 1. + /// Specifies if the image should be mounted in read-only mode. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + public static Task MountImageAsync(string imageFilePath, string mountPath, int imageIndex, bool readOnly, CancellationToken cancellationToken = default) + { + return MountImageAsync(imageFilePath, mountPath, imageIndex, readOnly, DismMountImageOptions.None, progress: null, cancellationToken); + } + + /// + /// Asynchronously mounts a WIM or VHD image file to a specified location. /// /// The path to the WIM or VHD file on the local computer. A .wim, .vhd, or .vhdx file name extension is required. /// The path of the location where the image should be mounted. This mount path must already exist on the computer. The Windows image in a .wim, .vhd, or .vhdx file can be mounted to an empty folder on an NTFS formatted drive. A Windows image in a .vhd or .vhdx file can also be mounted to an unassigned drive letter. You cannot mount an image to the root of the existing drive. /// The index of the image in the WIM file that you want to mount. For a VHD file, you must specify an index of 1. /// Specifies if the image should be mounted in read-only mode. /// Specifies options to use when mounting an image. - /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. + /// An optional provider to receive progress updates. + /// A token to monitor for cancellation requests. The default value is . /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. - public static Task MountImageAsync(string imageFilePath, string mountPath, int imageIndex, bool readOnly, DismMountImageOptions options, IProgress? progress, CancellationToken cancellationToken) + public static Task MountImageAsync(string imageFilePath, string mountPath, int imageIndex, bool readOnly, DismMountImageOptions options, IProgress? progress, CancellationToken cancellationToken = default) { - return MountImageAsync(imageFilePath, mountPath, imageIndex, null, DismImageIdentifier.ImageIndex, readOnly, options, progress, cancellationToken); + return MountImageAsync(imageFilePath, mountPath, imageIndex, readOnly, options, progress, userData: null, cancellationToken); } /// - /// Asynchronously mounts a WIM or VHD image file to a specified location using an image name. + /// Asynchronously mounts a WIM or VHD image file to a specified location. /// /// The path to the WIM or VHD file on the local computer. A .wim, .vhd, or .vhdx file name extension is required. /// The path of the location where the image should be mounted. This mount path must already exist on the computer. The Windows image in a .wim, .vhd, or .vhdx file can be mounted to an empty folder on an NTFS formatted drive. A Windows image in a .vhd or .vhdx file can also be mounted to an unassigned drive letter. You cannot mount an image to the root of the existing drive. - /// The name of the image that you want to mount. + /// The index of the image in the WIM file that you want to mount. For a VHD file, you must specify an index of 1. /// Specifies if the image should be mounted in read-only mode. /// Specifies options to use when mounting an image. - /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// A token to monitor for cancellation requests. The default value is . /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. - public static Task MountImageAsync(string imageFilePath, string mountPath, string? imageName, bool readOnly, DismMountImageOptions options, IProgress? progress, CancellationToken cancellationToken) + public static Task MountImageAsync(string imageFilePath, string mountPath, int imageIndex, bool readOnly, DismMountImageOptions options, IProgress? progress, object? userData, CancellationToken cancellationToken = default) { - return MountImageAsync(imageFilePath, mountPath, 0, imageName, DismImageIdentifier.ImageName, readOnly, options, progress, cancellationToken); + return DismUtilities.RunAsync( + static (state, progress) => + { + MountImage(state.imageFilePath, state.mountPath, state.imageIndex, state.readOnly, state.options, progress); + + return true; + }, + (imageFilePath, mountPath, imageIndex, readOnly, options), + progress, + userData, + cancellationToken); } /// /// Asynchronously mounts a WIM or VHD image file to a specified location. /// - private static Task MountImageAsync(string imageFilePath, string mountPath, int imageIndex, string? imageName, DismImageIdentifier imageIdentifier, bool readOnly, DismMountImageOptions options, IProgress? progress, CancellationToken cancellationToken) + /// The path to the WIM or VHD file on the local computer. A .wim, .vhd, or .vhdx file name extension is required. + /// The path of the location where the image should be mounted. This mount path must already exist on the computer. The Windows image in a .wim, .vhd, or .vhdx file can be mounted to an empty folder on an NTFS formatted drive. A Windows image in a .vhd or .vhdx file can also be mounted to an unassigned drive letter. You cannot mount an image to the root of the existing drive. + /// The name of the image that you want to mount. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + public static Task MountImageAsync(string imageFilePath, string mountPath, string? imageName, CancellationToken cancellationToken = default) + { + return MountImageAsync(imageFilePath, mountPath, imageName, readOnly: false, cancellationToken); + } + + /// + /// Asynchronously mounts a WIM or VHD image file to a specified location. + /// + /// The path to the WIM or VHD file on the local computer. A .wim, .vhd, or .vhdx file name extension is required. + /// The path of the location where the image should be mounted. This mount path must already exist on the computer. The Windows image in a .wim, .vhd, or .vhdx file can be mounted to an empty folder on an NTFS formatted drive. A Windows image in a .vhd or .vhdx file can also be mounted to an unassigned drive letter. You cannot mount an image to the root of the existing drive. + /// The name of the image that you want to mount. + /// Specifies if the image should be mounted in read-only mode. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + public static Task MountImageAsync(string imageFilePath, string mountPath, string? imageName, bool readOnly, CancellationToken cancellationToken = default) { - TaskCompletionSource tcs = new(); + return MountImageAsync(imageFilePath, mountPath, imageName, readOnly, DismMountImageOptions.None, progress: null, cancellationToken); + } - CancellationTokenRegistration ctsRegistration = default; + /// + /// Asynchronously mounts a WIM or VHD image file to a specified location. + /// + /// The path to the WIM or VHD file on the local computer. A .wim, .vhd, or .vhdx file name extension is required. + /// The path of the location where the image should be mounted. This mount path must already exist on the computer. The Windows image in a .wim, .vhd, or .vhdx file can be mounted to an empty folder on an NTFS formatted drive. A Windows image in a .vhd or .vhdx file can also be mounted to an unassigned drive letter. You cannot mount an image to the root of the existing drive. + /// The name of the image that you want to mount. + /// Specifies if the image should be mounted in read-only mode. + /// Specifies options to use when mounting an image. + /// An optional provider to receive progress updates. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + public static Task MountImageAsync(string imageFilePath, string mountPath, string? imageName, bool readOnly, DismMountImageOptions options, IProgress? progress, CancellationToken cancellationToken = default) + { + return MountImageAsync(imageFilePath, mountPath, imageName, readOnly, options, progress, userData: null, cancellationToken); + } - Task.Factory.StartNew( - () => + /// + /// Asynchronously mounts a WIM or VHD image file to a specified location. + /// + /// The path to the WIM or VHD file on the local computer. A .wim, .vhd, or .vhdx file name extension is required. + /// The path of the location where the image should be mounted. This mount path must already exist on the computer. The Windows image in a .wim, .vhd, or .vhdx file can be mounted to an empty folder on an NTFS formatted drive. A Windows image in a .vhd or .vhdx file can also be mounted to an unassigned drive letter. You cannot mount an image to the root of the existing drive. + /// The name of the image that you want to mount. + /// Specifies if the image should be mounted in read-only mode. + /// Specifies options to use when mounting an image. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + public static Task MountImageAsync(string imageFilePath, string mountPath, string? imageName, bool readOnly, DismMountImageOptions options, IProgress? progress, object? userData, CancellationToken cancellationToken = default) + { + return DismUtilities.RunAsync( + static (state, progress) => { - try - { - uint flags = (readOnly ? DISM_MOUNT_READONLY : DISM_MOUNT_READWRITE) | (uint)options; - - DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); - - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - - int hresult = NativeMethods.DismMountImage(imageFilePath, mountPath, (uint)imageIndex, imageName, imageIdentifier, flags, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - - if (cancellationToken.IsCancellationRequested) - { - tcs.TrySetCanceled(cancellationToken); - } - else - { - DismUtilities.ThrowIfFail(hresult); - tcs.TrySetResult(true); - } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - CancellationToken.None, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + MountImage(state.imageFilePath, state.mountPath, state.imageName, state.readOnly, state.options, progress); - return tcs.Task; + return true; + }, + (imageFilePath, mountPath, imageName, readOnly, options), + progress, + userData, + cancellationToken); } -#endif /// /// Mounts a WIM or VHD image file to a specified location. @@ -320,14 +386,28 @@ private static Task MountImageAsync(string imageFilePath, string mountPath, int /// Specifies options to use when mounting an image. /// A progress callback method to invoke when progress is made. /// Optional user data to pass to the DismProgressCallback method. - private static void MountImage(string imageFilePath, string mountPath, int imageIndex, string? imageName, DismImageIdentifier imageIdentifier, bool readOnly, DismMountImageOptions options, Microsoft.Dism.DismProgressCallback? progressCallback, object? userData) + private static void MountImage(string imageFilePath, string mountPath, int imageIndex, string? imageName, DismImageIdentifier imageIdentifier, bool readOnly, DismMountImageOptions options, DismProgressCallback? progressCallback, object? userData) + { + using DismProgress progress = new(progressCallback, userData); + + MountImage(imageFilePath, mountPath, imageIndex, imageName, imageIdentifier, readOnly, options, progress); + } + + private static void MountImage(string imageFilePath, string mountPath, int imageIndex, bool readOnly, DismMountImageOptions options, DismProgress progress) + { + MountImage(imageFilePath, mountPath, imageIndex, imageName: null, DismImageIdentifier.ImageIndex, readOnly, options, progress); + } + + private static void MountImage(string imageFilePath, string mountPath, string? imageName, bool readOnly, DismMountImageOptions options, DismProgress progress) + { + MountImage(imageFilePath, mountPath, 0, imageName, DismImageIdentifier.ImageName, readOnly, options, progress); + } + + private static void MountImage(string imageFilePath, string mountPath, int imageIndex, string? imageName, DismImageIdentifier imageIdentifier, bool readOnly, DismMountImageOptions options, DismProgress progress) { // Determine the flags to pass to the native call uint flags = (readOnly ? DISM_MOUNT_READONLY : DISM_MOUNT_READWRITE) | (uint)options; - // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new(progressCallback, userData); - int hresult = NativeMethods.DismMountImage(imageFilePath, mountPath, (uint)imageIndex, imageName, imageIdentifier, flags, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); DismUtilities.ThrowIfFail(hresult); @@ -347,12 +427,15 @@ internal static partial class NativeMethods /// Optional. You can set a CancelEvent for this function in order to cancel the operation in progress when signaled by the client. If the CancelEvent is received at a stage when the operation cannot be canceled, the operation will continue and return a success code. If the CancelEvent is received and the operation is canceled, the image state is unknown. You should verify the image state before continuing or discard the changes and start again. /// Optional. A pointer to a client-defined DismProgressCallback Function. /// Optional. User defined custom data. - /// Returns OK on success. + /// + /// Returns OK on success. /// /// Returns E_INVALIDARG if any of the paths are not well-formed or if MountPath or ImageFilePath does not exist or is invalid. /// - /// Returns a Win32 error code mapped to an HRESULT for other errors. - /// After mounting an image, use the DismOpenSession Function to start a servicing session. For more information, see Using the DISM API. + /// Returns a Win32 error code mapped to an HRESULT for other errors. + /// + /// + /// After mounting an image, use the DismOpenSession Function to start a servicing session. For more information, see Using the DISM API. /// /// Mounting an image from a WIM or VHD file that is stored on the network is not supported. You must specify a file on the local computer. /// @@ -362,16 +445,25 @@ internal static partial class NativeMethods /// /// When mounting an image in a WIM file, the image can either be identified by the image index number specified by ImageIndex, or the name of the image specified by ImageName. ImageIdentifier specifies whether to use the ImageIndex or ImageName parameter to identify the image. /// - /// - /// HRESULT WINAPI DismMountImage (_In_ PCWSTR ImageFilePath, _In_ PCWSTR MountPath, _In_ UINT ImageIndex, _In_opt_ PCWSTR ImageName, _In_ DismImageIdentifier ImageIdentifier, _In_ DWORD Flags, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); + /// HRESULT WINAPI DismMountImage (_In_ PCWSTR ImageFilePath, _In_ PCWSTR MountPath, _In_ UINT ImageIndex, _In_opt_ PCWSTR ImageName, _In_ DismImageIdentifier ImageIdentifier, _In_ DWORD Flags, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); /// - #if NET7_0_OR_GREATER +#if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismMountImage(string imageFilePath, string mountPath, UInt32 imageIndex, string? imageName, DismImageIdentifier imageIdentifier, UInt32 flags, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismMountImage(string imageFilePath, string mountPath, UInt32 imageIndex, string? imageName, DismImageIdentifier imageIdentifier, UInt32 flags, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #endif + public static extern +#endif + int DismMountImage( + string imageFilePath, + string mountPath, + UInt32 imageIndex, + string? imageName, + DismImageIdentifier imageIdentifier, + UInt32 flags, + SafeWaitHandle cancelEvent, + DismProgressCallbackNative progress, + IntPtr userData); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Dism/DismApi.OpenSession.cs b/src/Microsoft.Dism/DismApi.OpenSession.cs index 03ea652..e0fe18b 100644 --- a/src/Microsoft.Dism/DismApi.OpenSession.cs +++ b/src/Microsoft.Dism/DismApi.OpenSession.cs @@ -88,11 +88,16 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismOpenSession(string imagePath, string? windowsDirectory, string? systemDrive, out IntPtr session); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismOpenSession(string imagePath, string? windowsDirectory, string? systemDrive, out IntPtr session); - #endif + public static extern +#endif + int DismOpenSession( + string imagePath, + string? windowsDirectory, + string? systemDrive, + out IntPtr session); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.RemountImage.cs b/src/Microsoft.Dism/DismApi.RemountImage.cs index 6213a13..6aab978 100644 --- a/src/Microsoft.Dism/DismApi.RemountImage.cs +++ b/src/Microsoft.Dism/DismApi.RemountImage.cs @@ -37,11 +37,13 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismRemountImage(string mountPath); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismRemountImage(string mountPath); - #endif + public static extern +#endif + int DismRemountImage( + string mountPath); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.RemoveCapability.cs b/src/Microsoft.Dism/DismApi.RemoveCapability.cs index ae97d4c..fcb1c9e 100644 --- a/src/Microsoft.Dism/DismApi.RemoveCapability.cs +++ b/src/Microsoft.Dism/DismApi.RemoveCapability.cs @@ -21,7 +21,21 @@ public static partial class DismApi /// When the operation requires a reboot to complete. public static void RemoveCapability(DismSession session, string capabilityName) { - RemoveCapability(session, capabilityName, progressCallback: null, userData: null); + RemoveCapability(session, capabilityName, progressCallback: null); + } + + /// + /// Removes the capability from an image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the capability that is being removed + /// A progress callback method to invoke when progress is made. + /// When a failure occurs. + /// When the user requested the operation be canceled. + /// When the operation requires a reboot to complete. + public static void RemoveCapability(DismSession session, string capabilityName, DismProgressCallback? progressCallback) + { + RemoveCapability(session, capabilityName, progressCallback, userData: null); } /// @@ -34,75 +48,77 @@ public static void RemoveCapability(DismSession session, string capabilityName) /// When a failure occurs. /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static void RemoveCapability(DismSession session, string capabilityName, Dism.DismProgressCallback? progressCallback, object? userData) + public static void RemoveCapability(DismSession session, string capabilityName, DismProgressCallback? progressCallback, object? userData) { - // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new(progressCallback, userData); + using DismProgress progress = new(progressCallback, userData); - int hresult = NativeMethods.DismRemoveCapability(session, capabilityName, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); + RemoveCapability(session, capabilityName, progress); + } - DismUtilities.ThrowIfFail(hresult, session); + /// + /// Asynchronously removes the capability from an image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the capability that is being removed. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task RemoveCapabilityAsync(DismSession session, string capabilityName, CancellationToken cancellationToken = default) + { + return RemoveCapabilityAsync(session, capabilityName, progress: null, cancellationToken); } -#if !NET40 /// /// Asynchronously removes the capability from an image. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The name of the capability that is being removed. /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. + /// A token to monitor for cancellation requests. The default value is . /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. /// When the operation requires a reboot to complete. - public static Task RemoveCapabilityAsync(DismSession session, string capabilityName, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task RemoveCapabilityAsync(DismSession session, string capabilityName, IProgress? progress, CancellationToken cancellationToken = default) { - TaskCompletionSource tcs = new(); - - CancellationTokenRegistration ctsRegistration = default; + return RemoveCapabilityAsync(session, capabilityName, progress, userData: null, cancellationToken); + } - Task.Factory.StartNew( - () => + /// + /// Asynchronously removes the capability from an image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The name of the capability that is being removed. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task RemoveCapabilityAsync(DismSession session, string capabilityName, IProgress? progress, object? userData, CancellationToken cancellationToken = default) + { + return DismUtilities.RunAsync( + static (state, progress) => { - try - { - DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); - - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + RemoveCapability(state.session, state.capabilityName, progress); - int hresult = NativeMethods.DismRemoveCapability(session, capabilityName, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - - if (cancellationToken.IsCancellationRequested) - { - tcs.TrySetCanceled(cancellationToken); - } - else - { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); - } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } + return true; }, - CancellationToken.None, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + (session, capabilityName), + progress, + userData, + cancellationToken); + } - return tcs.Task; + private static void RemoveCapability(DismSession session, string capabilityName, DismProgress progress) + { + int hresult = NativeMethods.DismRemoveCapability(session, capabilityName, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); + + DismUtilities.ThrowIfFail(hresult, session); } -#endif internal static partial class NativeMethods { @@ -115,17 +131,20 @@ internal static partial class NativeMethods /// Pointer to a client defined callback function to report progress. /// User defined custom data. This will be passed back to the user through the callback. /// Returns S_OK on success. - /// - /// - /// HRESULT WINAPI DismRemoveCapability(_In_ DismSession Session, _In_ PCWSTR Name, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); - /// - #if NET7_0_OR_GREATER + /// HRESULT WINAPI DismRemoveCapability(_In_ DismSession Session, _In_ PCWSTR Name, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); +#if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismRemoveCapability(DismSession session, string name, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismRemoveCapability(DismSession session, string name, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #endif + public static extern +#endif + int DismRemoveCapability( + DismSession session, + string name, + SafeWaitHandle cancelEvent, + DismProgressCallbackNative progress, + IntPtr userData); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Dism/DismApi.RemovePackage.cs b/src/Microsoft.Dism/DismApi.RemovePackage.cs index 6f71699..c0c5a9e 100644 --- a/src/Microsoft.Dism/DismApi.RemovePackage.cs +++ b/src/Microsoft.Dism/DismApi.RemovePackage.cs @@ -33,7 +33,7 @@ public static void RemovePackageByName(DismSession session, string packageName) /// When a failure occurs. /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static void RemovePackageByName(DismSession session, string packageName, Dism.DismProgressCallback? progressCallback) + public static void RemovePackageByName(DismSession session, string packageName, DismProgressCallback? progressCallback) { RemovePackageByName(session, packageName, progressCallback, userData: null); } @@ -48,7 +48,7 @@ public static void RemovePackageByName(DismSession session, string packageName, /// When a failure occurs. /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static void RemovePackageByName(DismSession session, string packageName, Dism.DismProgressCallback? progressCallback, object? userData) + public static void RemovePackageByName(DismSession session, string packageName, DismProgressCallback? progressCallback, object? userData) { RemovePackage(session, packageName, DismPackageIdentifier.Name, progressCallback, userData); } @@ -74,7 +74,7 @@ public static void RemovePackageByPath(DismSession session, string packagePath) /// When a failure occurs. /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static void RemovePackageByPath(DismSession session, string packagePath, Dism.DismProgressCallback? progressCallback) + public static void RemovePackageByPath(DismSession session, string packagePath, DismProgressCallback? progressCallback) { RemovePackageByPath(session, packagePath, progressCallback, userData: null); } @@ -89,94 +89,126 @@ public static void RemovePackageByPath(DismSession session, string packagePath, /// When a failure occurs. /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static void RemovePackageByPath(DismSession session, string packagePath, Dism.DismProgressCallback? progressCallback, object? userData) + public static void RemovePackageByPath(DismSession session, string packagePath, DismProgressCallback? progressCallback, object? userData) { RemovePackage(session, packagePath, DismPackageIdentifier.Path, progressCallback, userData); } -#if !NET40 /// - /// Asynchronously removes a package from an image by name. + /// Asynchronously removes a package by package name from an image. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. /// The package name. - /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. + /// A token to monitor for cancellation requests. The default value is . /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. /// When the operation requires a reboot to complete. - public static Task RemovePackageByNameAsync(DismSession session, string packageName, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task RemovePackageByNameAsync(DismSession session, string packageName, CancellationToken cancellationToken = default) { - return RemovePackageAsync(session, packageName, DismPackageIdentifier.Name, progress, cancellationToken); + return RemovePackageByNameAsync(session, packageName, progress: null, cancellationToken); } /// - /// Asynchronously removes a package from an image by path. + /// Asynchronously removes a package by package name from an image. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. - /// The package path. + /// The package name. /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. + /// A token to monitor for cancellation requests. The default value is . /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. /// When the operation requires a reboot to complete. - public static Task RemovePackageByPathAsync(DismSession session, string packagePath, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task RemovePackageByNameAsync(DismSession session, string packageName, IProgress? progress, CancellationToken cancellationToken = default) { - return RemovePackageAsync(session, packagePath, DismPackageIdentifier.Path, progress, cancellationToken); + return RemovePackageByNameAsync(session, packageName, progress, userData: null, cancellationToken); } /// - /// Asynchronously removes a package from an image. + /// Asynchronously removes a package by package name from an image. /// - private static Task RemovePackageAsync(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, IProgress? progress, CancellationToken cancellationToken) + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The package name. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task RemovePackageByNameAsync(DismSession session, string packageName, IProgress? progress, object? userData, CancellationToken cancellationToken = default) { - TaskCompletionSource tcs = new(); + return DismUtilities.RunAsync( + static (state, progress) => + { + RemovePackage(state.session, state.packageName, DismPackageIdentifier.Name, progress); + + return true; + }, + (session, packageName), + progress, + userData, + cancellationToken); + } - CancellationTokenRegistration ctsRegistration = default; + /// + /// Asynchronously removes a package by package path from an image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The package path. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task RemovePackageByPathAsync(DismSession session, string packagePath, CancellationToken cancellationToken = default) + { + return RemovePackageByPathAsync(session, packagePath, progress: null, cancellationToken); + } - Task.Factory.StartNew( - () => + /// + /// Asynchronously removes a package by package path from an image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The package path. + /// An optional progress provider to receive progress updates. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task RemovePackageByPathAsync(DismSession session, string packagePath, IProgress? progress, CancellationToken cancellationToken = default) + { + return RemovePackageByPathAsync(session, packagePath, progress, userData: null, cancellationToken); + } + + /// + /// Asynchronously removes a package by package path from an image. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// The package path. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task RemovePackageByPathAsync(DismSession session, string packagePath, IProgress? progress, object? userData, CancellationToken cancellationToken = default) + { + return DismUtilities.RunAsync( + static (state, progress) => { - try - { - DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); - - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - - int hresult = NativeMethods.DismRemovePackage(session, identifier, packageIdentifier, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - - if (cancellationToken.IsCancellationRequested) - { - tcs.TrySetCanceled(cancellationToken); - } - else - { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); - } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - CancellationToken.None, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + RemovePackage(state.session, state.packagePath, DismPackageIdentifier.Path, progress); - return tcs.Task; + return true; + }, + (session, packagePath), + progress, + userData, + cancellationToken); } -#endif /// /// Removes a package from an image. @@ -186,11 +218,15 @@ private static Task RemovePackageAsync(DismSession session, string identifier, D /// A DismPackageIdentifier Enumeration. /// A progress callback method to invoke when progress is made. /// Optional user data to pass to the DismProgressCallback method. - private static void RemovePackage(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, Dism.DismProgressCallback? progressCallback, object? userData) + private static void RemovePackage(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, DismProgressCallback? progressCallback, object? userData) { - // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new(progressCallback, userData); + using DismProgress progress = new(progressCallback, userData); + + RemovePackage(session, identifier, packageIdentifier, progress); + } + private static void RemovePackage(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, DismProgress progress) + { int hresult = NativeMethods.DismRemovePackage(session, identifier, packageIdentifier, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); DismUtilities.ThrowIfFail(hresult, session); @@ -211,13 +247,20 @@ internal static partial class NativeMethods /// The DismRemovePackage function does not support .msu files. /// /// HRESULT WINAPI DismRemovePackage (_In_ DismSession Session, _In_ PCWSTR Identifier, _In_ DismPackageIdentifier PackageIdentifier, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); - #if NET7_0_OR_GREATER +#if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismRemovePackage(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, SafeWaitHandle cancelEvent, DismProgressCallback? progress, IntPtr userData); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismRemovePackage(DismSession session, string identifier, DismPackageIdentifier packageIdentifier, SafeWaitHandle cancelEvent, DismProgressCallback? progress, IntPtr userData); - #endif + public static extern +#endif + int DismRemovePackage( + DismSession session, + string identifier, + DismPackageIdentifier packageIdentifier, + SafeWaitHandle cancelEvent, + DismProgressCallbackNative? progress, + IntPtr userData); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Dism/DismApi.RemoveProvisionedAppxPackage.cs b/src/Microsoft.Dism/DismApi.RemoveProvisionedAppxPackage.cs index b6d996a..7acab4f 100644 --- a/src/Microsoft.Dism/DismApi.RemoveProvisionedAppxPackage.cs +++ b/src/Microsoft.Dism/DismApi.RemoveProvisionedAppxPackage.cs @@ -31,11 +31,14 @@ internal static partial class NativeMethods /// Returns S_OK on success. #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int _DismRemoveProvisionedAppxPackage(DismSession session, [MarshalAs(UnmanagedType.LPWStr)] string packageName); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int _DismRemoveProvisionedAppxPackage(DismSession session, [MarshalAs(UnmanagedType.LPWStr)] string packageName); - #endif + public static extern +#endif + int _DismRemoveProvisionedAppxPackage( + DismSession session, + [MarshalAs(UnmanagedType.LPWStr)] string packageName); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs b/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs index 7f350fa..be2bd70 100644 --- a/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs +++ b/src/Microsoft.Dism/DismApi.RestoreImageHealth.cs @@ -48,7 +48,7 @@ public static void RestoreImageHealth(DismSession session, bool limitAccess, Lis /// When a failure occurs. /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static void RestoreImageHealth(DismSession session, bool limitAccess, List? sourcePaths, Dism.DismProgressCallback? progressCallback) + public static void RestoreImageHealth(DismSession session, bool limitAccess, List? sourcePaths, DismProgressCallback? progressCallback) { RestoreImageHealth(session, limitAccess, sourcePaths, progressCallback, userData: null); } @@ -64,20 +64,44 @@ public static void RestoreImageHealth(DismSession session, bool limitAccess, Lis /// When a failure occurs. /// When the user requested the operation be canceled. /// When the operation requires a reboot to complete. - public static void RestoreImageHealth(DismSession session, bool limitAccess, List? sourcePaths, Dism.DismProgressCallback? progressCallback, object? userData) + public static void RestoreImageHealth(DismSession session, bool limitAccess, List? sourcePaths, DismProgressCallback? progressCallback, object? userData) { - // Get the list of source paths as an array - string[] sourcePathsArray = sourcePaths?.ToArray() ?? []; + using DismProgress progress = new(progressCallback, userData); - // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new(progressCallback, userData); + RestoreImageHealth(session, limitAccess, sourcePaths, progress); + } - int hresult = NativeMethods.DismRestoreImageHealth(session, sourcePathsArray, (uint)sourcePathsArray.Length, limitAccess, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); + /// + /// Asynchronously repairs a corrupted image that has been identified as repairable by the CheckImageHealth Function. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// Specifies whether the RestoreImageHealth method should contact Windows Update (WU) as a source location for downloading repair files. Before checking WU, DISM will check for the files in the sourcePaths provided and in any locations specified in the registry by Group Policy. If the files that are required to enable the feature are found in these other specified locations, this flag is ignored. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task RestoreImageHealthAsync(DismSession session, bool limitAccess, CancellationToken cancellationToken = default) + { + return RestoreImageHealthAsync(session, limitAccess, sourcePaths: null, progress: null, cancellationToken); + } - DismUtilities.ThrowIfFail(hresult, session); + /// + /// Asynchronously repairs a corrupted image that has been identified as repairable by the CheckImageHealth Function. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// Specifies whether the RestoreImageHealth method should contact Windows Update (WU) as a source location for downloading repair files. Before checking WU, DISM will check for the files in the sourcePaths provided and in any locations specified in the registry by Group Policy. If the files that are required to enable the feature are found in these other specified locations, this flag is ignored. + /// List of source locations to check for repair files. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task RestoreImageHealthAsync(DismSession session, bool limitAccess, List? sourcePaths, CancellationToken cancellationToken = default) + { + return RestoreImageHealthAsync(session, limitAccess, sourcePaths, progress: null, cancellationToken); } -#if !NET40 /// /// Asynchronously repairs a corrupted image that has been identified as repairable by the CheckImageHealth Function. /// @@ -85,60 +109,52 @@ public static void RestoreImageHealth(DismSession session, bool limitAccess, Lis /// Specifies whether the RestoreImageHealth method should contact Windows Update (WU) as a source location for downloading repair files. Before checking WU, DISM will check for the files in the sourcePaths provided and in any locations specified in the registry by Group Policy. If the files that are required to enable the feature are found in these other specified locations, this flag is ignored. /// List of source locations to check for repair files. /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. + /// A token to monitor for cancellation requests. The default value is . /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. /// When the operation requires a reboot to complete. - public static Task RestoreImageHealthAsync(DismSession session, bool limitAccess, List? sourcePaths = null, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task RestoreImageHealthAsync(DismSession session, bool limitAccess, List? sourcePaths, IProgress? progress, CancellationToken cancellationToken = default) { - TaskCompletionSource tcs = new(); - - CancellationTokenRegistration ctsRegistration = default; + return RestoreImageHealthAsync(session, limitAccess, sourcePaths, progress, userData: null, cancellationToken); + } - Task.Factory.StartNew( - () => + /// + /// Asynchronously repairs a corrupted image that has been identified as repairable by the CheckImageHealth Function. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the DismOpenSession Function. + /// Specifies whether the RestoreImageHealth method should contact Windows Update (WU) as a source location for downloading repair files. Before checking WU, DISM will check for the files in the sourcePaths provided and in any locations specified in the registry by Group Policy. If the files that are required to enable the feature are found in these other specified locations, this flag is ignored. + /// List of source locations to check for repair files. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task RestoreImageHealthAsync(DismSession session, bool limitAccess, List? sourcePaths, IProgress? progress, object? userData, CancellationToken cancellationToken = default) + { + return DismUtilities.RunAsync( + static (state, progress) => { - try - { - string[] sourcePathsArray = sourcePaths?.ToArray() ?? []; - - DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); + RestoreImageHealth(state.session, state.limitAccess, state.sourcePaths, progress); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + return true; + }, + (session, limitAccess, sourcePaths), + progress, + userData, + cancellationToken); + } - int hresult = NativeMethods.DismRestoreImageHealth(session, sourcePathsArray, (uint)sourcePathsArray.Length, limitAccess, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + private static void RestoreImageHealth(DismSession session, bool limitAccess, List? sourcePaths, DismProgress progress) + { + string[] sourcePathsArray = sourcePaths?.ToArray() ?? []; - if (cancellationToken.IsCancellationRequested) - { - tcs.TrySetCanceled(cancellationToken); - } - else - { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); - } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - CancellationToken.None, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + int hresult = NativeMethods.DismRestoreImageHealth(session, sourcePathsArray, (uint)sourcePathsArray.Length, limitAccess, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); - return tcs.Task; + DismUtilities.ThrowIfFail(hresult, session); } -#endif internal static partial class NativeMethods { @@ -153,20 +169,28 @@ internal static partial class NativeMethods /// Optional. A pointer to a client-defined DismProgressCallback Function. /// Optional. User defined custom data. /// Returns S_OK on success. - /// Run the DismCheckImageHealth Function to determine if the image is corrupted and if the image is repairable. If the DismCheckImageHealth Function returns DismImageRepairable, the DismRestoreImageHealth function can repair the image. + /// + /// Run the DismCheckImageHealth Function to determine if the image is corrupted and if the image is repairable. If the DismCheckImageHealth Function returns DismImageRepairable, the DismRestoreImageHealth function can repair the image. /// /// If a repair file is not found in any of the locations specified by the SourcePaths parameter or the location paths in the registry specified by Group Policy, the DismRestoreImageHealth function will contact WU to check for a repair file unless the LimitAccess parameter is set to True. /// - /// - /// HRESULT WINAPI DismRestoreImageHealth(_In_ DismSession Session, _In_reads_opt_(SourcePathCount) PCWSTR* SourcePaths, _In_opt_ UINT SourcePathCount, _In_ BOOL LimitAccess, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); + /// HRESULT WINAPI DismRestoreImageHealth(_In_ DismSession Session, _In_reads_opt_(SourcePathCount) PCWSTR* SourcePaths, _In_opt_ UINT SourcePathCount, _In_ BOOL LimitAccess, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); /// - #if NET7_0_OR_GREATER +#if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismRestoreImageHealth(DismSession session, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)] string[] sourcePaths, UInt32 sourcePathCount, [MarshalAs(UnmanagedType.Bool)] bool limitAccess, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismRestoreImageHealth(DismSession session, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)] string[] sourcePaths, UInt32 sourcePathCount, [MarshalAs(UnmanagedType.Bool)] bool limitAccess, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #endif + public static extern +#endif + int DismRestoreImageHealth( + DismSession session, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)] string[] sourcePaths, + UInt32 sourcePathCount, + [MarshalAs(UnmanagedType.Bool)] bool limitAccess, + SafeWaitHandle cancelEvent, + DismProgressCallbackNative progress, + IntPtr userData); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Dism/DismApi.SetEdition.cs b/src/Microsoft.Dism/DismApi.SetEdition.cs index b8d73f8..92c22a7 100644 --- a/src/Microsoft.Dism/DismApi.SetEdition.cs +++ b/src/Microsoft.Dism/DismApi.SetEdition.cs @@ -32,7 +32,7 @@ public static void SetEdition(DismSession session, string editionId) /// A progress callback method to invoke when progress is made. /// When a failure occurs. /// When the operation requires a reboot to complete. - public static void SetEdition(DismSession session, string editionId, Dism.DismProgressCallback? progressCallback) + public static void SetEdition(DismSession session, string editionId, DismProgressCallback? progressCallback) { SetEdition(session, editionId, progressCallback, userData: null); } @@ -46,7 +46,7 @@ public static void SetEdition(DismSession session, string editionId, Dism.DismPr /// Optional user data to pass to the DismProgressCallback method. /// When a failure occurs. /// When the operation requires a reboot to complete. - public static void SetEdition(DismSession session, string editionId, Dism.DismProgressCallback? progressCallback, object? userData) + public static void SetEdition(DismSession session, string editionId, DismProgressCallback? progressCallback, object? userData) { SetEdition(session, editionId, productKey: null, progressCallback, userData); } @@ -73,7 +73,7 @@ public static void SetEditionAndProductKey(DismSession session, string editionId /// A progress callback method to invoke when progress is made. /// When a failure occurs. /// When the operation requires a reboot to complete. - public static void SetEditionAndProductKey(DismSession session, string editionId, string productKey, Dism.DismProgressCallback? progressCallback) + public static void SetEditionAndProductKey(DismSession session, string editionId, string productKey, DismProgressCallback? progressCallback) { SetEditionAndProductKey(session, editionId, productKey, progressCallback, userData: null); } @@ -88,26 +88,25 @@ public static void SetEditionAndProductKey(DismSession session, string editionId /// Optional user data to pass to the DismProgressCallback method. /// When a failure occurs. /// When the operation requires a reboot to complete. - public static void SetEditionAndProductKey(DismSession session, string editionId, string productKey, Dism.DismProgressCallback? progressCallback, object? userData) + public static void SetEditionAndProductKey(DismSession session, string editionId, string productKey, DismProgressCallback? progressCallback, object? userData) { SetEdition(session, editionId, productKey, progressCallback, userData); } -#if !NET40 /// - /// Asynchronously changes an offline Windows image to a higher edition. + /// Asynchronously changes an offline Windows image to a higher edition and sets the product key. /// /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. /// The edition to set the image to. - /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. + /// A product key for the specified edition. + /// A token to monitor for cancellation requests. The default value is . /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. /// When the operation requires a reboot to complete. - public static Task SetEditionAsync(DismSession session, string editionId, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task SetEditionAndProductKeyAsync(DismSession session, string editionId, string productKey, CancellationToken cancellationToken = default) { - return SetEditionAsync(session, editionId, productKey: null, progress, cancellationToken); + return SetEditionAndProductKeyAsync(session, editionId, productKey, progress: null, cancellationToken); } /// @@ -117,66 +116,101 @@ public static Task SetEditionAsync(DismSession session, string editionId, IProgr /// The edition to set the image to. /// A product key for the specified edition. /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. + /// A token to monitor for cancellation requests. The default value is . /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. /// When the operation requires a reboot to complete. - public static Task SetEditionAndProductKeyAsync(DismSession session, string editionId, string productKey, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task SetEditionAndProductKeyAsync(DismSession session, string editionId, string productKey, IProgress? progress, CancellationToken cancellationToken = default) { - return SetEditionAsync(session, editionId, productKey, progress, cancellationToken); + return SetEditionAndProductKeyAsync(session, editionId, productKey, progress, userData: null, cancellationToken); } /// - /// Asynchronously changes an offline Windows image to a higher edition and optionally sets the product key. + /// Asynchronously changes an offline Windows image to a higher edition and sets the product key. /// - private static Task SetEditionAsync(DismSession session, string editionId, string? productKey, IProgress? progress, CancellationToken cancellationToken) + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. + /// The edition to set the image to. + /// A product key for the specified edition. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task SetEditionAndProductKeyAsync(DismSession session, string editionId, string productKey, IProgress? progress, object? userData, CancellationToken cancellationToken = default) { - TaskCompletionSource tcs = new(); + return DismUtilities.RunAsync( + static (state, progress) => + { + SetEdition(state.session, state.editionId, state.productKey, progress); + + return true; + }, + (session, editionId, productKey), + progress, + userData, + cancellationToken); + } - CancellationTokenRegistration ctsRegistration = default; + /// + /// Asynchronously changes an offline Windows image to a higher edition. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. + /// The edition to set the image to. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task SetEditionAsync(DismSession session, string editionId, CancellationToken cancellationToken = default) + { + return SetEditionAsync(session, editionId, progress: null, cancellationToken); + } + + /// + /// Asynchronously changes an offline Windows image to a higher edition. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. + /// The edition to set the image to. + /// An optional progress provider to receive progress updates. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task SetEditionAsync(DismSession session, string editionId, IProgress? progress, CancellationToken cancellationToken = default) + { + return SetEditionAsync(session, editionId, progress, userData: null, cancellationToken); + } - Task.Factory.StartNew( - () => + /// + /// Asynchronously changes an offline Windows image to a higher edition. + /// + /// A valid DISM Session. The DISM Session must be associated with an image. You can associate a session with an image by using the method. + /// The edition to set the image to. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + /// When the operation requires a reboot to complete. + public static Task SetEditionAsync(DismSession session, string editionId, IProgress? progress, object? userData, CancellationToken cancellationToken = default) + { + return DismUtilities.RunAsync( + static (state, progress) => { - try - { - DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); - - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); - - int hresult = NativeMethods.DismSetEdition(session, editionId, productKey, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); - - if (cancellationToken.IsCancellationRequested) - { - tcs.TrySetCanceled(cancellationToken); - } - else - { - DismUtilities.ThrowIfFail(hresult, session); - tcs.TrySetResult(true); - } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - CancellationToken.None, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + SetEdition(state.session, state.editionId, productKey: null, progress); - return tcs.Task; + return true; + }, + (session, editionId), + progress, + userData, + cancellationToken); } -#endif /// /// Changes an offline Windows image to a higher edition and optionaly sets the product key. @@ -188,11 +222,15 @@ private static Task SetEditionAsync(DismSession session, string editionId, strin /// Optional user data to pass to the DismProgressCallback method. /// When a failure occurs. /// When the operation requires a reboot to complete. - private static void SetEdition(DismSession session, string editionId, string? productKey, Dism.DismProgressCallback? progressCallback, object? userData) + private static void SetEdition(DismSession session, string editionId, string? productKey, DismProgressCallback? progressCallback, object? userData) { - // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new(progressCallback, userData); + using DismProgress progress = new(progressCallback, userData); + + SetEdition(session, editionId, productKey, progress); + } + private static void SetEdition(DismSession session, string editionId, string? productKey, DismProgress progress) + { int hresult = NativeMethods.DismSetEdition(session, editionId, productKey, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); DismUtilities.ThrowIfFail(hresult, session); @@ -210,25 +248,20 @@ internal static partial class NativeMethods /// Optional. A pointer to a client-defined DismProgressCallback Function. /// Optional. User defined custom data. /// Returns S_OK on success. - #if NET7_0_OR_GREATER +#if NET7_0_OR_GREATER [LibraryImport(DismDllName, EntryPoint = "_DismSetEdition", StringMarshalling = DismStringMarshalling)] - public static partial int DismSetEdition( - DismSession session, - [MarshalAs(UnmanagedType.LPWStr)] string editionID, - [MarshalAs(UnmanagedType.LPWStr)] string? productKey, - SafeWaitHandle cancelEvent, - DismProgressCallback progress, - IntPtr userData); - #else + public static partial +#else [DllImport(DismDllName, EntryPoint = "_DismSetEdition", CharSet = DismCharacterSet)] - public static extern int DismSetEdition( + public static extern +#endif + int DismSetEdition( DismSession session, [MarshalAs(UnmanagedType.LPWStr)] string editionID, [MarshalAs(UnmanagedType.LPWStr)] string? productKey, SafeWaitHandle cancelEvent, - DismProgressCallback progress, + DismProgressCallbackNative progress, IntPtr userData); - #endif } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Dism/DismApi.SetProductKey.cs b/src/Microsoft.Dism/DismApi.SetProductKey.cs index 235d7fb..54aba4c 100644 --- a/src/Microsoft.Dism/DismApi.SetProductKey.cs +++ b/src/Microsoft.Dism/DismApi.SetProductKey.cs @@ -31,11 +31,14 @@ internal static partial class NativeMethods /// Returns S_OK on success. #if NET7_0_OR_GREATER [LibraryImport(DismDllName, EntryPoint = "_DismSetProductKey", StringMarshalling = DismStringMarshalling)] - public static partial int DismSetProductKey(DismSession session, string productKey); - #else + public static partial +#else [DllImport(DismDllName, EntryPoint = "_DismSetProductKey", CharSet = DismCharacterSet)] - public static extern int DismSetProductKey(DismSession session, string productKey); - #endif + public static extern +#endif + int DismSetProductKey( + DismSession session, + string productKey); } } } diff --git a/src/Microsoft.Dism/DismApi.SplitFfuImage.cs b/src/Microsoft.Dism/DismApi.SplitFfuImage.cs index 1c8c942..c76fa3e 100644 --- a/src/Microsoft.Dism/DismApi.SplitFfuImage.cs +++ b/src/Microsoft.Dism/DismApi.SplitFfuImage.cs @@ -30,11 +30,15 @@ internal static partial class NativeMethods /// Retrusn S_OK on success. #if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int _DismSplitFfuImage([MarshalAs(UnmanagedType.LPWStr)] string ImagePath, [MarshalAs(UnmanagedType.LPWStr)] string PartPath, ulong PartSize); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int _DismSplitFfuImage([MarshalAs(UnmanagedType.LPWStr)] string ImagePath, [MarshalAs(UnmanagedType.LPWStr)] string PartPath, ulong PartSize); - #endif + public static extern +#endif + int _DismSplitFfuImage( + [MarshalAs(UnmanagedType.LPWStr)] string ImagePath, + [MarshalAs(UnmanagedType.LPWStr)] string PartPath, + ulong PartSize); } } } \ No newline at end of file diff --git a/src/Microsoft.Dism/DismApi.UnmountImage.cs b/src/Microsoft.Dism/DismApi.UnmountImage.cs index 7331b5d..0f991cf 100644 --- a/src/Microsoft.Dism/DismApi.UnmountImage.cs +++ b/src/Microsoft.Dism/DismApi.UnmountImage.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. using Microsoft.Win32.SafeHandles; + using System; using System.Runtime.InteropServices; using System.Threading; @@ -31,7 +32,7 @@ public static void UnmountImage(string mountPath, bool commitChanges) /// A progress callback method to invoke when progress is made. /// When a failure occurs. /// When the user requested the operation be canceled. - public static void UnmountImage(string mountPath, bool commitChanges, Dism.DismProgressCallback? progressCallback) + public static void UnmountImage(string mountPath, bool commitChanges, DismProgressCallback? progressCallback) { UnmountImage(mountPath, commitChanges, progressCallback, userData: null); } @@ -45,79 +46,76 @@ public static void UnmountImage(string mountPath, bool commitChanges, Dism.DismP /// Optional user data to pass to the DismProgressCallback method. /// When a failure occurs. /// When the user requested the operation be canceled. - public static void UnmountImage(string mountPath, bool commitChanges, Dism.DismProgressCallback? progressCallback, object? userData) + public static void UnmountImage(string mountPath, bool commitChanges, DismProgressCallback? progressCallback, object? userData) { - // Determine flags - uint flags = commitChanges ? DISM_COMMIT_IMAGE : DISM_DISCARD_IMAGE; - - // Create a DismProgress object to wrap the callback and allow cancellation - DismProgress progress = new(progressCallback, userData); + using DismProgress progress = new(progressCallback, userData); - int hresult = NativeMethods.DismUnmountImage(mountPath, flags, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); + UnmountImage(mountPath, commitChanges, progress); + } - DismUtilities.ThrowIfFail(hresult); + /// + /// Asynchronously unmounts a Windows image from a specified location. + /// + /// A relative or absolute path to the mount directory of the image. + /// Specifies whether or not the changes to the image should be saved. + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + public static Task UnmountImageAsync(string mountPath, bool commitChanges, CancellationToken cancellationToken = default) + { + return UnmountImageAsync(mountPath, commitChanges, progress: null, cancellationToken); } -#if !NET40 /// /// Asynchronously unmounts a Windows image from a specified location. /// /// A relative or absolute path to the mount directory of the image. /// Specifies whether or not the changes to the image should be saved. /// An optional progress provider to receive progress updates. - /// A cancellation token to cancel the operation. + /// A token to monitor for cancellation requests. The default value is . /// A representing the asynchronous operation. /// When a failure occurs. /// When the operation is canceled. - public static Task UnmountImageAsync(string mountPath, bool commitChanges, IProgress? progress = null, CancellationToken cancellationToken = default) + public static Task UnmountImageAsync(string mountPath, bool commitChanges, IProgress? progress, CancellationToken cancellationToken = default) { - TaskCompletionSource tcs = new(); - - CancellationTokenRegistration ctsRegistration = default; + return UnmountImageAsync(mountPath, commitChanges, progress, userData: null, cancellationToken); + } - Task.Factory.StartNew( - () => + /// + /// Asynchronously unmounts a Windows image from a specified location. + /// + /// A relative or absolute path to the mount directory of the image. + /// Specifies whether or not the changes to the image should be saved. + /// An optional provider to receive progress updates. + /// Optional user data to pass to the specified . + /// A token to monitor for cancellation requests. The default value is . + /// A representing the asynchronous operation. + /// When a failure occurs. + /// When the operation is canceled. + public static Task UnmountImageAsync(string mountPath, bool commitChanges, IProgress? progress, object? userData, CancellationToken cancellationToken = default) + { + return DismUtilities.RunAsync( + static (state, progress) => { - try - { - uint flags = commitChanges ? DISM_COMMIT_IMAGE : DISM_DISCARD_IMAGE; - - DismProgress dismProgress = new(progress != null ? p => progress.Report(p) : null, null); + UnmountImage(state.mountPath, state.commitChanges, progress); - ctsRegistration = cancellationToken.Register(() => dismProgress.Cancel = true); + return true; + }, + (mountPath, commitChanges), + progress, + userData, + cancellationToken); + } - int hresult = NativeMethods.DismUnmountImage(mountPath, flags, dismProgress.EventHandle, dismProgress.DismProgressCallbackNative, IntPtr.Zero); + private static void UnmountImage(string mountPath, bool commitChanges, DismProgress progress) + { + uint flags = commitChanges ? DISM_COMMIT_IMAGE : DISM_DISCARD_IMAGE; - if (cancellationToken.IsCancellationRequested) - { - tcs.TrySetCanceled(cancellationToken); - } - else - { - DismUtilities.ThrowIfFail(hresult); - tcs.TrySetResult(true); - } - } - catch (OperationCanceledException) - { - tcs.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - tcs.TrySetException(ex); - } - finally - { - ctsRegistration.Dispose(); - } - }, - CancellationToken.None, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + int hresult = NativeMethods.DismUnmountImage(mountPath, flags, progress.EventHandle, progress.DismProgressCallbackNative, IntPtr.Zero); - return tcs.Task; + DismUtilities.ThrowIfFail(hresult); } -#endif internal static partial class NativeMethods { @@ -130,18 +128,24 @@ internal static partial class NativeMethods /// Optional. A pointer to a client-defined DismProgressCallback Function. /// Optional. User defined custom data. /// Returns OK on success. - /// After you use the DismCloseSession Function to end every active DISMSession, you can unmount the image using the DismUnmountImage function. + /// + /// After you use the DismCloseSession Function to end every active DISMSession, you can unmount the image using the DismUnmountImage function. /// - /// - /// HRESULT WINAPI DismUnmountImage(_In_ PCWSTR MountPath, _In_ DWORD Flags, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); + /// HRESULT WINAPI DismUnmountImage(_In_ PCWSTR MountPath, _In_ DWORD Flags, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress, _In_opt_ PVOID UserData); /// - #if NET7_0_OR_GREATER +#if NET7_0_OR_GREATER [LibraryImport(DismDllName, StringMarshalling = DismStringMarshalling)] - public static partial int DismUnmountImage(string mountPath, UInt32 flags, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #else + public static partial +#else [DllImport(DismDllName, CharSet = DismCharacterSet)] - public static extern int DismUnmountImage(string mountPath, UInt32 flags, SafeWaitHandle cancelEvent, DismProgressCallback progress, IntPtr userData); - #endif + public static extern +#endif + int DismUnmountImage( + string mountPath, + UInt32 flags, + SafeWaitHandle cancelEvent, + DismProgressCallbackNative progress, + IntPtr userData); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Dism/DismApi.ValidateProductKey.cs b/src/Microsoft.Dism/DismApi.ValidateProductKey.cs index 700a85c..347bf34 100644 --- a/src/Microsoft.Dism/DismApi.ValidateProductKey.cs +++ b/src/Microsoft.Dism/DismApi.ValidateProductKey.cs @@ -45,11 +45,14 @@ internal static partial class NativeMethods /// #if NET7_0_OR_GREATER [LibraryImport(DismDllName, EntryPoint = "_DismValidateProductKey", StringMarshalling = DismStringMarshalling)] - public static partial int DismValidateProductKey(DismSession session, string productKey); - #else + public static partial +#else [DllImport(DismDllName, EntryPoint = "_DismValidateProductKey", CharSet = DismCharacterSet)] - public static extern int DismValidateProductKey(DismSession session, string productKey); - #endif + public static extern +#endif + int DismValidateProductKey( + DismSession session, + string productKey); } } } diff --git a/src/Microsoft.Dism/DismCustomProperty.cs b/src/Microsoft.Dism/DismCustomProperty.cs index 13a091f..e344552 100644 --- a/src/Microsoft.Dism/DismCustomProperty.cs +++ b/src/Microsoft.Dism/DismCustomProperty.cs @@ -87,7 +87,7 @@ public override bool Equals(object? obj) /// Determines whether the specified is equal to the current . /// /// A object to compare with the current object. - /// true if the specified is equal to the current , otherwise . + /// if the specified is equal to the current , otherwise . public bool Equals(DismCustomProperty? other) { return other != null diff --git a/src/Microsoft.Dism/DismProgress.cs b/src/Microsoft.Dism/DismProgress.cs index 359090a..bbe1033 100644 --- a/src/Microsoft.Dism/DismProgress.cs +++ b/src/Microsoft.Dism/DismProgress.cs @@ -24,6 +24,8 @@ public sealed class DismProgress : IDisposable /// private readonly EventWaitHandle _eventHandle; + private readonly CancellationTokenRegistration? _cancellationTokenRegistration; + /// /// Initializes a new instance of the class. /// @@ -41,6 +43,12 @@ internal DismProgress(DismProgressCallback? callback, object? userData) _eventHandle = new EventWaitHandle(false, EventResetMode.ManualReset); } + internal DismProgress(IProgress? progress, object? userData, CancellationToken? cancellationToken) + : this((p) => progress?.Report(p), userData) + { + _cancellationTokenRegistration = cancellationToken?.Register(() => Cancel = true); + } + /// /// Gets or sets a value indicating whether the operation should be canceled if possible. /// @@ -87,6 +95,8 @@ public object? UserData /// public void Dispose() { + _cancellationTokenRegistration?.Dispose(); + // Clean up the event handle _eventHandle?.Dispose(); } diff --git a/src/Microsoft.Dism/DismProgressCallback.cs b/src/Microsoft.Dism/DismProgressCallback.cs index 022e11e..72f2d1d 100644 --- a/src/Microsoft.Dism/DismProgressCallback.cs +++ b/src/Microsoft.Dism/DismProgressCallback.cs @@ -26,6 +26,6 @@ public static partial class DismApi /// void DismProgressCallback(_In_ UINT Current, _In_ UINT Total, _In_ PVOID UserData) /// [UnmanagedFunctionPointer(CallingConvention.Winapi)] - internal delegate void DismProgressCallback(UInt32 current, UInt32 total, IntPtr userData); + internal delegate void DismProgressCallbackNative(UInt32 current, UInt32 total, IntPtr userData); } } diff --git a/src/Microsoft.Dism/DismUtilities.cs b/src/Microsoft.Dism/DismUtilities.cs index 29bbd4d..a6d6181 100644 --- a/src/Microsoft.Dism/DismUtilities.cs +++ b/src/Microsoft.Dism/DismUtilities.cs @@ -63,6 +63,8 @@ cannot be installed at the same time. using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.Dism { @@ -295,6 +297,43 @@ internal static void ThrowIfFail(int hresult, DismSession? session = null, [Call return dismPath.Exists ? dismPath.FullName : null; } + internal static Task RunAsync(Func action, TState state, IProgress? progress, object? userData, CancellationToken cancellationToken = default) + { + TaskCompletionSource taskCompletionSource = new(); + + Task.Factory.StartNew( + () => + { + if (cancellationToken.IsCancellationRequested) + { + taskCompletionSource.TrySetCanceled(cancellationToken); + return; + } + + using DismProgress dismProgress = new(progress, userData, cancellationToken); + + try + { + TResult result = action(state, dismProgress); + + taskCompletionSource.TrySetResult(result); + } + catch (OperationCanceledException) + { + taskCompletionSource.TrySetCanceled(cancellationToken); + } + catch (Exception ex) + { + taskCompletionSource.TrySetException(ex); + } + }, + CancellationToken.None, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return taskCompletionSource.Task; + } + /// /// Native methods necessary for manually loading and unloading Win32 libraries. /// diff --git a/src/Microsoft.Dism/GlobalSuppressions.cs b/src/Microsoft.Dism/GlobalSuppressions.cs index cc1f8da..a73ba5b 100644 --- a/src/Microsoft.Dism/GlobalSuppressions.cs +++ b/src/Microsoft.Dism/GlobalSuppressions.cs @@ -8,8 +8,65 @@ // a specific target and scoped to a namespace, type, member, etc. using System.Diagnostics.CodeAnalysis; -[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "This library only works on Windows", Scope = "member", Target = "~P:Microsoft.Dism.DismUtilities.WAIKDISMAPIPath")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.AddPackageAsync(Microsoft.Dism.DismSession,System.String,System.Boolean,System.Boolean,System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.AddPackageAsync(Microsoft.Dism.DismSession,System.String,System.Boolean,System.Boolean,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.CommitImageAsync(Microsoft.Dism.DismSession,System.Boolean,System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.CommitImageAsync(Microsoft.Dism.DismSession,System.Boolean,System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.CommitImageAsync(Microsoft.Dism.DismSession,System.Boolean,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.DisableFeatureAsync(Microsoft.Dism.DismSession,System.String,System.String,System.Boolean,System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.DisableFeatureAsync(Microsoft.Dism.DismSession,System.String,System.String,System.Boolean,System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.DisableFeatureAsync(Microsoft.Dism.DismSession,System.String,System.String,System.Boolean,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.EnableFeatureAsync(Microsoft.Dism.DismSession,System.String,System.Boolean,System.Boolean,System.Collections.Generic.List{System.String},System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.EnableFeatureAsync(Microsoft.Dism.DismSession,System.String,System.Boolean,System.Boolean,System.Collections.Generic.List{System.String},System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.EnableFeatureAsync(Microsoft.Dism.DismSession,System.String,System.Boolean,System.Boolean,System.Collections.Generic.List{System.String},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.EnableFeatureAsync(Microsoft.Dism.DismSession,System.String,System.Boolean,System.Boolean,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.EnableFeatureByPackageNameAsync(Microsoft.Dism.DismSession,System.String,System.String,System.Boolean,System.Boolean,System.Collections.Generic.List{System.String},System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.EnableFeatureByPackageNameAsync(Microsoft.Dism.DismSession,System.String,System.String,System.Boolean,System.Boolean,System.Collections.Generic.List{System.String},System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.EnableFeatureByPackageNameAsync(Microsoft.Dism.DismSession,System.String,System.String,System.Boolean,System.Boolean,System.Collections.Generic.List{System.String},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.EnableFeatureByPackageNameAsync(Microsoft.Dism.DismSession,System.String,System.String,System.Boolean,System.Boolean,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.EnableFeatureByPackagePathAsync(Microsoft.Dism.DismSession,System.String,System.String,System.Boolean,System.Boolean,System.Collections.Generic.List{System.String},System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.EnableFeatureByPackagePathAsync(Microsoft.Dism.DismSession,System.String,System.String,System.Boolean,System.Boolean,System.Collections.Generic.List{System.String},System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.EnableFeatureByPackagePathAsync(Microsoft.Dism.DismSession,System.String,System.String,System.Boolean,System.Boolean,System.Collections.Generic.List{System.String},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.EnableFeatureByPackagePathAsync(Microsoft.Dism.DismSession,System.String,System.String,System.Boolean,System.Boolean,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.MountImageAsync(System.String,System.String,System.Int32,System.Boolean,Microsoft.Dism.DismMountImageOptions,System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.MountImageAsync(System.String,System.String,System.Int32,System.Boolean,Microsoft.Dism.DismMountImageOptions,System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.MountImageAsync(System.String,System.String,System.Int32,System.Boolean,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.MountImageAsync(System.String,System.String,System.Int32,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.MountImageAsync(System.String,System.String,System.String,System.Boolean,Microsoft.Dism.DismMountImageOptions,System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.MountImageAsync(System.String,System.String,System.String,System.Boolean,Microsoft.Dism.DismMountImageOptions,System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.MountImageAsync(System.String,System.String,System.String,System.Boolean,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.MountImageAsync(System.String,System.String,System.String,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.RemoveCapabilityAsync(Microsoft.Dism.DismSession,System.String,System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.RemoveCapabilityAsync(Microsoft.Dism.DismSession,System.String,System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.RemoveCapabilityAsync(Microsoft.Dism.DismSession,System.String,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.RemovePackageByNameAsync(Microsoft.Dism.DismSession,System.String,System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.RemovePackageByNameAsync(Microsoft.Dism.DismSession,System.String,System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.RemovePackageByNameAsync(Microsoft.Dism.DismSession,System.String,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.RemovePackageByPathAsync(Microsoft.Dism.DismSession,System.String,System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.RemovePackageByPathAsync(Microsoft.Dism.DismSession,System.String,System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.RemovePackageByPathAsync(Microsoft.Dism.DismSession,System.String,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.RestoreImageHealthAsync(Microsoft.Dism.DismSession,System.Boolean,System.Collections.Generic.List{System.String},System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.RestoreImageHealthAsync(Microsoft.Dism.DismSession,System.Boolean,System.Collections.Generic.List{System.String},System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.RestoreImageHealthAsync(Microsoft.Dism.DismSession,System.Boolean,System.Collections.Generic.List{System.String},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.RestoreImageHealthAsync(Microsoft.Dism.DismSession,System.Boolean,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.SetEditionAndProductKeyAsync(Microsoft.Dism.DismSession,System.String,System.String,System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.SetEditionAndProductKeyAsync(Microsoft.Dism.DismSession,System.String,System.String,System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.SetEditionAndProductKeyAsync(Microsoft.Dism.DismSession,System.String,System.String,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.SetEditionAsync(Microsoft.Dism.DismSession,System.String,System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.SetEditionAsync(Microsoft.Dism.DismSession,System.String,System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.SetEditionAsync(Microsoft.Dism.DismSession,System.String,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.UnmountImageAsync(System.String,System.Boolean,System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.UnmountImageAsync(System.String,System.Boolean,System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.UnmountImageAsync(System.String,System.Boolean,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.AddCapabilityAsync(Microsoft.Dism.DismSession,System.String,System.Boolean,System.Collections.Generic.List{System.String},System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.AddCapabilityAsync(Microsoft.Dism.DismSession,System.String,System.Boolean,System.Collections.Generic.List{System.String},System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.AddCapabilityAsync(Microsoft.Dism.DismSession,System.String,System.Boolean,System.Collections.Generic.List{System.String},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.AddPackageAsync(Microsoft.Dism.DismSession,System.String,System.Boolean,System.Boolean,System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.CheckImageHealthAsync(Microsoft.Dism.DismSession,System.Boolean,System.IProgress{Microsoft.Dism.DismProgress},System.Object,System.Threading.CancellationToken)~System.Threading.Tasks.Task{Microsoft.Dism.DismImageHealthState}")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.CheckImageHealthAsync(Microsoft.Dism.DismSession,System.Boolean,System.IProgress{Microsoft.Dism.DismProgress},System.Threading.CancellationToken)~System.Threading.Tasks.Task{Microsoft.Dism.DismImageHealthState}")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "This is a new method", Scope = "member", Target = "~M:Microsoft.Dism.DismApi.CheckImageHealthAsync(Microsoft.Dism.DismSession,System.Boolean,System.Threading.CancellationToken)~System.Threading.Tasks.Task{Microsoft.Dism.DismImageHealthState}")] +[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "This library only works on Windows", Scope = "member", Target = "~M:Microsoft.Dism.DismUtilities.GetKitsRoot(System.String)")] [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "This library only works on Windows", Scope = "member", Target = "~P:Microsoft.Dism.DismUtilities.WADK10DismApiPath")] [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "This library only works on Windows", Scope = "member", Target = "~P:Microsoft.Dism.DismUtilities.WADK80DISMAPIPath")] [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "This library only works on Windows", Scope = "member", Target = "~P:Microsoft.Dism.DismUtilities.WADK81DISMAPIPath")] -[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "This library only works on Windows", Scope = "member", Target = "~M:Microsoft.Dism.DismUtilities.GetKitsRoot(System.String)")] +[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "This library only works on Windows", Scope = "member", Target = "~P:Microsoft.Dism.DismUtilities.WAIKDISMAPIPath")] diff --git a/src/Microsoft.Dism/Microsoft.Dism.csproj b/src/Microsoft.Dism/Microsoft.Dism.csproj index 39b9aad..1ea8577 100644 --- a/src/Microsoft.Dism/Microsoft.Dism.csproj +++ b/src/Microsoft.Dism/Microsoft.Dism.csproj @@ -1,6 +1,6 @@  - net40;netstandard2.0;net8.0;net10.0 + net472;netstandard2.0;net8.0;net10.0 true true Managed API for Deployment Image Servicing and Management (DISM) @@ -10,7 +10,7 @@ $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb true true - $(NoWarn);RS0016;RS0017 + $(NoWarn);RS0016;RS0017 diff --git a/src/Microsoft.Dism/PublicAPI.Unshipped.txt b/src/Microsoft.Dism/PublicAPI.Unshipped.txt index 75bba0a..5cb000e 100644 --- a/src/Microsoft.Dism/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Dism/PublicAPI.Unshipped.txt @@ -1,18 +1,59 @@ #nullable enable -static Microsoft.Dism.DismApi.AddCapabilityAsync(Microsoft.Dism.DismSession! session, string! capabilityName, bool limitAccess, System.Collections.Generic.List? sourcePaths, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.AddPackageAsync(Microsoft.Dism.DismSession! session, string! packagePath, bool ignoreCheck, bool preventPending, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.CheckImageHealthAsync(Microsoft.Dism.DismSession! session, bool scanImage, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.CommitImageAsync(Microsoft.Dism.DismSession! session, bool discardChanges, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.DisableFeatureAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packageName, bool removePayload, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.EnableFeatureAsync(Microsoft.Dism.DismSession! session, string! featureName, bool limitAccess, bool enableAll, System.Collections.Generic.List? sourcePaths = null, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.EnableFeatureByPackageNameAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packageName, bool limitAccess, bool enableAll, System.Collections.Generic.List? sourcePaths = null, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.EnableFeatureByPackagePathAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packagePath, bool limitAccess, bool enableAll, System.Collections.Generic.List? sourcePaths = null, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.MountImageAsync(string! imageFilePath, string! mountPath, int imageIndex, bool readOnly, Microsoft.Dism.DismMountImageOptions options, System.IProgress? progress, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.MountImageAsync(string! imageFilePath, string! mountPath, string? imageName, bool readOnly, Microsoft.Dism.DismMountImageOptions options, System.IProgress? progress, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.RemoveCapabilityAsync(Microsoft.Dism.DismSession! session, string! capabilityName, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.RemovePackageByNameAsync(Microsoft.Dism.DismSession! session, string! packageName, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.RemovePackageByPathAsync(Microsoft.Dism.DismSession! session, string! packagePath, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.RestoreImageHealthAsync(Microsoft.Dism.DismSession! session, bool limitAccess, System.Collections.Generic.List? sourcePaths = null, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.SetEditionAndProductKeyAsync(Microsoft.Dism.DismSession! session, string! editionId, string! productKey, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.SetEditionAsync(Microsoft.Dism.DismSession! session, string! editionId, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! -static Microsoft.Dism.DismApi.UnmountImageAsync(string! mountPath, bool commitChanges, System.IProgress? progress = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.AddCapabilityAsync(Microsoft.Dism.DismSession! session, string! capabilityName, bool limitAccess, System.Collections.Generic.List? sourcePaths, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.AddCapabilityAsync(Microsoft.Dism.DismSession! session, string! capabilityName, bool limitAccess, System.Collections.Generic.List? sourcePaths, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.AddCapabilityAsync(Microsoft.Dism.DismSession! session, string! capabilityName, bool limitAccess, System.Collections.Generic.List? sourcePaths, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.AddPackageAsync(Microsoft.Dism.DismSession! session, string! packagePath, bool ignoreCheck, bool preventPending, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.AddPackageAsync(Microsoft.Dism.DismSession! session, string! packagePath, bool ignoreCheck, bool preventPending, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.AddPackageAsync(Microsoft.Dism.DismSession! session, string! packagePath, bool ignoreCheck, bool preventPending, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.CheckImageHealthAsync(Microsoft.Dism.DismSession! session, bool scanImage, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.CheckImageHealthAsync(Microsoft.Dism.DismSession! session, bool scanImage, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.CheckImageHealthAsync(Microsoft.Dism.DismSession! session, bool scanImage, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.CommitImageAsync(Microsoft.Dism.DismSession! session, bool discardChanges, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.CommitImageAsync(Microsoft.Dism.DismSession! session, bool discardChanges, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.CommitImageAsync(Microsoft.Dism.DismSession! session, bool discardChanges, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.DisableFeatureAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packageName, bool removePayload, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.DisableFeatureAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packageName, bool removePayload, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.DisableFeatureAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packageName, bool removePayload, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.EnableFeatureAsync(Microsoft.Dism.DismSession! session, string! featureName, bool limitAccess, bool enableAll, System.Collections.Generic.List? sourcePaths, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.EnableFeatureAsync(Microsoft.Dism.DismSession! session, string! featureName, bool limitAccess, bool enableAll, System.Collections.Generic.List? sourcePaths, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.EnableFeatureAsync(Microsoft.Dism.DismSession! session, string! featureName, bool limitAccess, bool enableAll, System.Collections.Generic.List? sourcePaths, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.EnableFeatureAsync(Microsoft.Dism.DismSession! session, string! featureName, bool limitAccess, bool enableAll, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.EnableFeatureByPackageNameAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packageName, bool limitAccess, bool enableAll, System.Collections.Generic.List? sourcePaths, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.EnableFeatureByPackageNameAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packageName, bool limitAccess, bool enableAll, System.Collections.Generic.List? sourcePaths, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.EnableFeatureByPackageNameAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packageName, bool limitAccess, bool enableAll, System.Collections.Generic.List? sourcePaths, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.EnableFeatureByPackageNameAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packageName, bool limitAccess, bool enableAll, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.EnableFeatureByPackagePathAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packagePath, bool limitAccess, bool enableAll, System.Collections.Generic.List? sourcePaths, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.EnableFeatureByPackagePathAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packagePath, bool limitAccess, bool enableAll, System.Collections.Generic.List? sourcePaths, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.EnableFeatureByPackagePathAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packagePath, bool limitAccess, bool enableAll, System.Collections.Generic.List? sourcePaths, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.EnableFeatureByPackagePathAsync(Microsoft.Dism.DismSession! session, string! featureName, string! packagePath, bool limitAccess, bool enableAll, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.MountImageAsync(string! imageFilePath, string! mountPath, int imageIndex, bool readOnly, Microsoft.Dism.DismMountImageOptions options, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.MountImageAsync(string! imageFilePath, string! mountPath, int imageIndex, bool readOnly, Microsoft.Dism.DismMountImageOptions options, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.MountImageAsync(string! imageFilePath, string! mountPath, int imageIndex, bool readOnly, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.MountImageAsync(string! imageFilePath, string! mountPath, int imageIndex, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.MountImageAsync(string! imageFilePath, string! mountPath, string? imageName, bool readOnly, Microsoft.Dism.DismMountImageOptions options, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.MountImageAsync(string! imageFilePath, string! mountPath, string? imageName, bool readOnly, Microsoft.Dism.DismMountImageOptions options, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.MountImageAsync(string! imageFilePath, string! mountPath, string? imageName, bool readOnly, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.MountImageAsync(string! imageFilePath, string! mountPath, string? imageName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RemoveCapability(Microsoft.Dism.DismSession! session, string! capabilityName, Microsoft.Dism.DismProgressCallback? progressCallback) -> void +static Microsoft.Dism.DismApi.RemoveCapabilityAsync(Microsoft.Dism.DismSession! session, string! capabilityName, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RemoveCapabilityAsync(Microsoft.Dism.DismSession! session, string! capabilityName, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RemoveCapabilityAsync(Microsoft.Dism.DismSession! session, string! capabilityName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RemovePackageByNameAsync(Microsoft.Dism.DismSession! session, string! packageName, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RemovePackageByNameAsync(Microsoft.Dism.DismSession! session, string! packageName, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RemovePackageByNameAsync(Microsoft.Dism.DismSession! session, string! packageName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RemovePackageByPathAsync(Microsoft.Dism.DismSession! session, string! packagePath, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RemovePackageByPathAsync(Microsoft.Dism.DismSession! session, string! packagePath, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RemovePackageByPathAsync(Microsoft.Dism.DismSession! session, string! packagePath, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RestoreImageHealthAsync(Microsoft.Dism.DismSession! session, bool limitAccess, System.Collections.Generic.List? sourcePaths, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RestoreImageHealthAsync(Microsoft.Dism.DismSession! session, bool limitAccess, System.Collections.Generic.List? sourcePaths, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RestoreImageHealthAsync(Microsoft.Dism.DismSession! session, bool limitAccess, System.Collections.Generic.List? sourcePaths, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.RestoreImageHealthAsync(Microsoft.Dism.DismSession! session, bool limitAccess, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.SetEditionAndProductKeyAsync(Microsoft.Dism.DismSession! session, string! editionId, string! productKey, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.SetEditionAndProductKeyAsync(Microsoft.Dism.DismSession! session, string! editionId, string! productKey, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.SetEditionAndProductKeyAsync(Microsoft.Dism.DismSession! session, string! editionId, string! productKey, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.SetEditionAsync(Microsoft.Dism.DismSession! session, string! editionId, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.SetEditionAsync(Microsoft.Dism.DismSession! session, string! editionId, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.SetEditionAsync(Microsoft.Dism.DismSession! session, string! editionId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.UnmountImageAsync(string! mountPath, bool commitChanges, System.IProgress? progress, object? userData, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.UnmountImageAsync(string! mountPath, bool commitChanges, System.IProgress? progress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static Microsoft.Dism.DismApi.UnmountImageAsync(string! mountPath, bool commitChanges, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! diff --git a/src/Microsoft.Dism/SystemTime.cs b/src/Microsoft.Dism/SystemTime.cs index e746d30..bc7163e 100644 --- a/src/Microsoft.Dism/SystemTime.cs +++ b/src/Microsoft.Dism/SystemTime.cs @@ -74,7 +74,7 @@ internal struct SystemTime public WORD Milliseconds; /// - /// Converts a to a . + /// Converts a to a . /// /// The time to convert. public static implicit operator SystemTime(DateTime dateTime) @@ -95,7 +95,7 @@ public static implicit operator SystemTime(DateTime dateTime) } /// - /// Converts a to a + /// Converts a to a /// /// The time to convert. public static implicit operator DateTime(SystemTime systemTime)