mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Update PowerShell telemetry to respect the diagnostics and feedback setting on Windows (#27328)
This commit is contained in:
@@ -121,6 +121,18 @@
|
||||
value="0x3002"
|
||||
version="1"
|
||||
/>
|
||||
<!--Telemetry events-->
|
||||
<event
|
||||
channel="C_OPERATIONAL"
|
||||
level="win:Error"
|
||||
message="$(string.PS_PROVIDER.event.E_O_TelemetrySettingError.message)"
|
||||
opcode="Exception"
|
||||
symbol="TelemetrySettingError"
|
||||
task="Telemetry"
|
||||
template="T_TelemetrySettingError"
|
||||
value="0x3011"
|
||||
version="1"
|
||||
/>
|
||||
<!--M3P events-->
|
||||
<event
|
||||
channel="C_ANALYTIC"
|
||||
@@ -2208,17 +2220,41 @@
|
||||
value="0x6017"
|
||||
version="1"
|
||||
/>
|
||||
<event
|
||||
channel="C_ANALYTIC"
|
||||
keywords="AmsiState"
|
||||
level="win:Verbose"
|
||||
message="$(string.PS_PROVIDER.event.E_A_AmsiState.message)"
|
||||
opcode="Method"
|
||||
symbol="AmsiState"
|
||||
task="Amsi"
|
||||
template="T_AmsiState"
|
||||
value="0x4001"
|
||||
version="1"
|
||||
<event
|
||||
channel="C_ANALYTIC"
|
||||
keywords="AmsiState"
|
||||
level="win:Verbose"
|
||||
message="$(string.PS_PROVIDER.event.E_A_AmsiState.message)"
|
||||
opcode="Method"
|
||||
symbol="AmsiState"
|
||||
task="Amsi"
|
||||
template="T_AmsiState"
|
||||
value="0x4001"
|
||||
version="1"
|
||||
/>
|
||||
<event
|
||||
channel="C_ANALYTIC"
|
||||
keywords="WDACQuery"
|
||||
level="win:Verbose"
|
||||
message="$(string.PS_PROVIDER.event.E_A_WDACQuery.message)"
|
||||
opcode="Method"
|
||||
symbol="WDACQuery"
|
||||
task="WDAC"
|
||||
template="T_WDACQuery"
|
||||
value="0x4002"
|
||||
version="1"
|
||||
/>
|
||||
<event
|
||||
channel="C_ANALYTIC"
|
||||
keywords="WDACAudit"
|
||||
level="win:Verbose"
|
||||
message = "$(string.PS_PROVIDER.event.E_A_WDACAudit.message)"
|
||||
opcode="Method"
|
||||
symbol="WDACAudit"
|
||||
task="WDACAudit"
|
||||
template="T_WDACAudit"
|
||||
value="0x4003"
|
||||
version="1"
|
||||
/>
|
||||
</events>
|
||||
<channels>
|
||||
@@ -2409,6 +2445,12 @@
|
||||
symbol="T_EXPERIMENTALFEATURE"
|
||||
value="107"
|
||||
/>
|
||||
<task
|
||||
message="$(string.PS_PROVIDER.task.T_Telemetry.message)"
|
||||
name="Telemetry"
|
||||
symbol="T_TELEMETRY"
|
||||
value="108"
|
||||
/>
|
||||
<task
|
||||
message="$(string.PS_PROVIDER.task.T_ScheduledJob.message)"
|
||||
name="ScheduledJob"
|
||||
@@ -2427,11 +2469,23 @@
|
||||
symbol="T_ISEOperation"
|
||||
value="120"
|
||||
/>
|
||||
<task
|
||||
message="$(string.PS_PROVIDER.task.T_AmsiState.message)"
|
||||
name="Amsi"
|
||||
symbol="T_Amsi"
|
||||
value="130"
|
||||
<task
|
||||
message="$(string.PS_PROVIDER.task.T_AmsiState.message)"
|
||||
name="Amsi"
|
||||
symbol="T_Amsi"
|
||||
value="130"
|
||||
/>
|
||||
<task
|
||||
message="$(string.PS_PROVIDER.task.T_WDACQuery.message)"
|
||||
name="WDAC"
|
||||
symbol="T_WDAC"
|
||||
value="131"
|
||||
/>
|
||||
<task
|
||||
message="$(string.PS_PROVIDER.task.T_WDACAudit.message)"
|
||||
name="WDACAudit"
|
||||
symbol="T_WDACAudit"
|
||||
value="132"
|
||||
/>
|
||||
</tasks>
|
||||
<opcodes>
|
||||
@@ -2593,11 +2647,23 @@
|
||||
name="PSWorkflow"
|
||||
symbol="K_PSWORKFLOW"
|
||||
/>
|
||||
<keyword
|
||||
mask="0x400"
|
||||
message="$(string.PS_PROVIDER.keyword.K_AmsiState.message)"
|
||||
name="AmsiState"
|
||||
symbol="K_AmsiState"
|
||||
<keyword
|
||||
mask="0x400"
|
||||
message="$(string.PS_PROVIDER.keyword.K_AmsiState.message)"
|
||||
name="AmsiState"
|
||||
symbol="K_AmsiState"
|
||||
/>
|
||||
<keyword
|
||||
mask="0x800"
|
||||
message="$(string.PS_PROVIDER.keyword.K_WDACQuery.message)"
|
||||
name="WDACQuery"
|
||||
symbol="K_WDACQuery"
|
||||
/>
|
||||
<keyword
|
||||
mask="0x1000"
|
||||
message="$(string.PS_PROVIDER.keyword.K_WDACAudit.message)"
|
||||
name="WDACAudit"
|
||||
symbol="K_WDACAudit"
|
||||
/>
|
||||
</keywords>
|
||||
<maps>
|
||||
@@ -4004,6 +4070,20 @@
|
||||
name="StackTrace"
|
||||
/>
|
||||
</template>
|
||||
<template tid="T_TelemetrySettingError">
|
||||
<data
|
||||
inType="win:UnicodeString"
|
||||
name="Name"
|
||||
/>
|
||||
<data
|
||||
inType="win:UnicodeString"
|
||||
name="Message"
|
||||
/>
|
||||
<data
|
||||
inType="win:UnicodeString"
|
||||
name="StackTrace"
|
||||
/>
|
||||
</template>
|
||||
<template tid="T_TrackingGuid">
|
||||
<data
|
||||
inType="win:GUID"
|
||||
@@ -4080,16 +4160,48 @@
|
||||
name="FileName"
|
||||
/>
|
||||
</template>
|
||||
<template tid="T_AmsiState">
|
||||
<data
|
||||
inType="win:UnicodeString"
|
||||
name="Action"
|
||||
<template tid="T_AmsiState">
|
||||
<data
|
||||
inType="win:UnicodeString"
|
||||
name="Action"
|
||||
/>
|
||||
<data
|
||||
inType="win:UnicodeString"
|
||||
name="AmsiContext"
|
||||
<data
|
||||
inType="win:UnicodeString"
|
||||
name="AmsiContext"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
<template tid="T_WDACQuery">
|
||||
<data
|
||||
inType="win:UnicodeString"
|
||||
name="QueryName"
|
||||
/>
|
||||
<data
|
||||
inType="win:UnicodeString"
|
||||
name="FileName"
|
||||
/>
|
||||
<data
|
||||
inType="win:Int32"
|
||||
name="QuerySuccess"
|
||||
/>
|
||||
<data
|
||||
inType="win:Int32"
|
||||
name="QuerySResult"
|
||||
/>
|
||||
</template>
|
||||
<template tid="T_WDACAudit">
|
||||
<data
|
||||
inType="win:UnicodeString"
|
||||
name="Title"
|
||||
/>
|
||||
<data
|
||||
inType="win:UnicodeString"
|
||||
name="Message"
|
||||
/>
|
||||
<data
|
||||
inType="win:UnicodeString"
|
||||
name="FullyQualifiedId"
|
||||
/>
|
||||
</template>
|
||||
</templates>
|
||||
</provider>
|
||||
</events>
|
||||
@@ -5535,6 +5647,14 @@
|
||||
id="PS_PROVIDER.task.T_ExperimentalFeature.message"
|
||||
value="PowerShell Experimental Features"
|
||||
/>
|
||||
<string
|
||||
id="PS_PROVIDER.event.E_O_TelemetrySettingError.message"
|
||||
value="Failed to retrieve diagnostics and feedback setting from Windows.%n Exception: %1 %n Message: %2 %n StackTrace: %3 %n"
|
||||
/>
|
||||
<string
|
||||
id="PS_PROVIDER.task.T_Telemetry.message"
|
||||
value="PowerShell Telemetry"
|
||||
/>
|
||||
<string
|
||||
id="PS_PROVIDER.task.T_NamedPipe.message"
|
||||
value="PowerShell Named Pipe IPC"
|
||||
@@ -5719,6 +5839,30 @@
|
||||
id="PS_PROVIDER.event.E_O_REMOTE_NAMEDPIPE_DISCONNECT.message"
|
||||
value="PowerShell IPC disconnect on process: %1 in AppDomain: %2 for User: %3."
|
||||
/>
|
||||
<string
|
||||
id="PS_PROVIDER.event.E_A_WDACQuery.message"
|
||||
value="WDAC Query. %n %t Query: %1 %n %t File: %2 %n %t SuccessCode: %3 %n %t ResultCode: %4"
|
||||
/>
|
||||
<string
|
||||
id="PS_PROVIDER.keyword.K_WDACQuery.message"
|
||||
value="WDAC Query"
|
||||
/>
|
||||
<string
|
||||
id="PS_PROVIDER.task.T_WDACQuery.message"
|
||||
value="WDAC Query"
|
||||
/>
|
||||
<string
|
||||
id="PS_PROVIDER.event.E_A_WDACAudit.message"
|
||||
value="WDAC Audit. %n %t Title: %1 %n %t Message: %2 %n %t FullyQualifiedId: %3"
|
||||
/>
|
||||
<string
|
||||
id="PS_PROVIDER.keyword.K_WDACAudit.message"
|
||||
value="WDAC Audit"
|
||||
/>
|
||||
<string
|
||||
id="PS_PROVIDER.task.T_WDACAudit.message"
|
||||
value="WDAC Audit"
|
||||
/>
|
||||
</stringTable>
|
||||
</resources>
|
||||
</localization>
|
||||
|
||||
@@ -179,9 +179,12 @@ namespace System.Management.Automation
|
||||
{
|
||||
int result = Interop.Windows.CoInitializeEx(IntPtr.Zero, Interop.Windows.COINIT_APARTMENTTHREADED);
|
||||
|
||||
// If 0 is returned the thread has been initialized for the first time
|
||||
// as an STA and thus supported and needs to be uninitialized.
|
||||
if (result > 0)
|
||||
// Per COM documentation: Each successful call to CoInitializeEx (including S_FALSE)
|
||||
// must be balanced by a corresponding call to CoUninitialize.
|
||||
// - S_OK (0) means we initialized for the first time.
|
||||
// - S_FALSE (1) means already initialized, but still increments the reference count.
|
||||
// Both require CoUninitialize to decrement the reference count.
|
||||
if (result >= 0)
|
||||
{
|
||||
Interop.Windows.CoUninitialize();
|
||||
}
|
||||
|
||||
@@ -166,6 +166,9 @@ namespace System.Management.Automation.Internal
|
||||
ExperimentalFeature_InvalidName = 0x3001,
|
||||
ExperimentalFeature_ReadConfig_Error = 0x3002,
|
||||
|
||||
// Windows Diagnostics And Usage Data Settings
|
||||
Telemetry_Setting_Error = 0x3011,
|
||||
|
||||
// Scheduled Jobs
|
||||
ScheduledJob_Start = 0xD001,
|
||||
ScheduledJob_Complete = 0xD002,
|
||||
@@ -240,6 +243,7 @@ namespace System.Management.Automation.Internal
|
||||
ProviderStop = 0x69,
|
||||
ExecutePipeline = 0x6A,
|
||||
ExperimentalFeature = 0x6B,
|
||||
Telemetry = 0x6C,
|
||||
ScheduledJob = 0x6E,
|
||||
NamedPipe = 0x6F,
|
||||
ISEOperation = 0x78,
|
||||
|
||||
@@ -177,12 +177,20 @@ namespace Microsoft.PowerShell.Telemetry
|
||||
/// </summary>
|
||||
static ApplicationInsightsTelemetry()
|
||||
{
|
||||
// If we can't send telemetry, there's no reason to do any of this
|
||||
CanSendTelemetry = !Utils.GetEnvironmentVariableAsBool(name: _telemetryOptoutEnvVar, defaultValue: false)
|
||||
&& Platform.TryDeriveFromCache("telemetry.uuid", out s_uuidPath);
|
||||
|
||||
#if !UNIX
|
||||
if (CanSendTelemetry)
|
||||
{
|
||||
// Respect the diagnostics and feedback setting in Windows.
|
||||
CanSendTelemetry = WindowsDataCollectionSetting.CanCollectDiagnostics(PlatformDataCollectionLevel.Enhanced);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!CanSendTelemetry)
|
||||
{
|
||||
// Avoid the initialization work if we can't send telemetry.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#if !UNIX
|
||||
|
||||
using System;
|
||||
using System.Management.Automation.Internal;
|
||||
using System.Management.Automation.Tracing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.Marshalling;
|
||||
|
||||
namespace Microsoft.PowerShell.Telemetry;
|
||||
|
||||
internal enum PlatformDataCollectionLevel : int
|
||||
{
|
||||
/// <summary>
|
||||
/// Minimum — only security-related data. Enterprise/education editions only.
|
||||
/// </summary>
|
||||
Security = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Device info, capabilities, and basic reliability data.
|
||||
/// </summary>
|
||||
Basic = 1,
|
||||
|
||||
/// <summary>
|
||||
/// More detailed usage and reliability data, including app/feature usage patterns.
|
||||
/// Removed as a user-facing option in Windows 11 (collapsed into Full).
|
||||
/// </summary>
|
||||
Enhanced = 2,
|
||||
|
||||
/// <summary>
|
||||
/// All of the above plus advanced diagnostics data that can help Microsoft fix problems.
|
||||
/// </summary>
|
||||
Full = 3,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimal projection of <c>IInspectable</c>, the base interface for all WinRT objects.
|
||||
/// Slots 3–5 in every WinRT interface vtable (after <c>IUnknown</c>'s QueryInterface/AddRef/Release).
|
||||
/// </summary>
|
||||
[GeneratedComInterface]
|
||||
[Guid("AF86E2E0-B12D-4C6A-9C5A-D7AA65101E90")]
|
||||
internal partial interface IInspectable
|
||||
{
|
||||
void GetIids(out uint iidCount, out nint iids);
|
||||
|
||||
nint GetRuntimeClassName();
|
||||
|
||||
int GetTrustLevel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Projection of the WinRT interface <c>Windows.System.Profile.IPlatformDiagnosticsAndUsageDataSettingsStatics</c>
|
||||
/// (IID B6E24C1B-7B1C-4B32-8C62-A66597CE723A).
|
||||
/// Vtable slots 6–9, following the three <c>IInspectable</c> slots.
|
||||
/// </summary>
|
||||
[GeneratedComInterface]
|
||||
[Guid("B6E24C1B-7B1C-4B32-8C62-A66597CE723A")]
|
||||
internal partial interface IPlatformDiagnosticsAndUsageDataSettingsStatics : IInspectable
|
||||
{
|
||||
PlatformDataCollectionLevel GetCollectionLevel();
|
||||
|
||||
long AddCollectionLevelChanged(nint handler);
|
||||
|
||||
void RemoveCollectionLevelChanged(long token);
|
||||
|
||||
// WinRT marshals bool as a byte; use byte to avoid any MarshalAs ambiguity with the source generator.
|
||||
byte CanCollectDiagnostics(PlatformDataCollectionLevel level);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps <c>Windows.System.Profile.PlatformDiagnosticsAndUsageDataSettings</c> using compile-time COM interop
|
||||
/// and source-generated P/Invoke. No extra runtime DLLs are required.
|
||||
/// </summary>
|
||||
internal static partial class WindowsDataCollectionSetting
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns <see langword="true"/> if the device's diagnostic data collection policy permits collecting at or above <paramref name="level"/>.
|
||||
/// </summary>
|
||||
/// <param name="level">The minimum <see cref="PlatformDataCollectionLevel"/> to test against.</param>
|
||||
internal static bool CanCollectDiagnostics(PlatformDataCollectionLevel level)
|
||||
{
|
||||
const string ClassName = "Windows.System.Profile.PlatformDiagnosticsAndUsageDataSettings";
|
||||
|
||||
// When initializing WinRT on the calling thread, use the multi-threaded apartment (MTA).
|
||||
// This is to cover the case where PowerShell gets used in a thread-pool thread.
|
||||
// See the doc at https://learn.microsoft.com/windows/win32/api/roapi/ne-roapi-ro_init_type
|
||||
const int RO_INIT_MULTITHREADED = 1;
|
||||
|
||||
// Return values for 'RoInitialize':
|
||||
// - S_OK (0) - we successfully initialized; must call 'RoUninitialize'.
|
||||
// - S_FALSE (1) - already initialized with the same apartment type; must still call 'RoUninitialize'.
|
||||
// - RPC_E_CHANGED_MODE - already initialized with a different apartment type; WinRT still works, do NOT call 'RoUninitialize'.
|
||||
const int RPC_E_CHANGED_MODE = unchecked((int)0x80010106);
|
||||
|
||||
int initHr = -1;
|
||||
nint hstring = default;
|
||||
nint factoryPtr = default;
|
||||
|
||||
try
|
||||
{
|
||||
// Initialize WinRT on the calling thread. 'RoGetActivationFactory' requires it.
|
||||
initHr = RoInitialize(RO_INIT_MULTITHREADED);
|
||||
if (initHr < 0 && initHr != RPC_E_CHANGED_MODE)
|
||||
{
|
||||
// The call to initialize the Windows Runtime failed.
|
||||
// Throw an exception with the HRESULT error code to provide more context on the failure.
|
||||
Marshal.ThrowExceptionForHR(initHr);
|
||||
}
|
||||
|
||||
Marshal.ThrowExceptionForHR(
|
||||
WindowsCreateString(ClassName, (uint)ClassName.Length, out hstring));
|
||||
|
||||
Guid iid = new("B6E24C1B-7B1C-4B32-8C62-A66597CE723A");
|
||||
Marshal.ThrowExceptionForHR(
|
||||
RoGetActivationFactory(hstring, ref iid, out factoryPtr));
|
||||
|
||||
var comWrappers = new StrategyBasedComWrappers();
|
||||
var comObject = comWrappers.GetOrCreateObjectForComInstance(factoryPtr, CreateObjectFlags.None);
|
||||
var platformSetting = (IPlatformDiagnosticsAndUsageDataSettingsStatics)comObject;
|
||||
|
||||
return platformSetting.CanCollectDiagnostics(level) != 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log any exceptions that occur during this process, but swallow them and return false to disable telemetry rather than crashing the product.
|
||||
// This API is only used to gate telemetry collection, so failure should be non-fatal.
|
||||
PSEtwLog.LogOperationalError(
|
||||
PSEventId.Telemetry_Setting_Error,
|
||||
PSOpcode.Exception,
|
||||
PSTask.Telemetry,
|
||||
PSKeyword.UseAlwaysOperational,
|
||||
ex.GetType().FullName,
|
||||
ex.Message,
|
||||
ex.StackTrace);
|
||||
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (factoryPtr != default)
|
||||
{
|
||||
Marshal.Release(factoryPtr);
|
||||
}
|
||||
|
||||
if (hstring != default)
|
||||
{
|
||||
_ = WindowsDeleteString(hstring);
|
||||
}
|
||||
|
||||
// Per COM documentation: Each successful call to 'RoInitialize' (including S_FALSE)
|
||||
// must be balanced by a corresponding call to 'RoUninitialize'.
|
||||
if (initHr >= 0)
|
||||
{
|
||||
RoUninitialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport("api-ms-win-core-winrt-string-l1-1-0.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
|
||||
private static partial int WindowsCreateString(
|
||||
string sourceString,
|
||||
uint length,
|
||||
out nint hstring);
|
||||
|
||||
[LibraryImport("api-ms-win-core-winrt-string-l1-1-0.dll")]
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
|
||||
private static partial int WindowsDeleteString(nint hstring);
|
||||
|
||||
[LibraryImport("api-ms-win-core-winrt-l1-1-0.dll")]
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
|
||||
private static partial int RoGetActivationFactory(nint activatableClassId, ref Guid iid, out nint factory);
|
||||
|
||||
[LibraryImport("api-ms-win-core-winrt-l1-1-0.dll")]
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
|
||||
private static partial int RoInitialize(int initType);
|
||||
|
||||
[LibraryImport("api-ms-win-core-winrt-l1-1-0.dll")]
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
|
||||
private static partial void RoUninitialize();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -5,8 +5,53 @@
|
||||
# these tests aren't going to check that telemetry is being sent
|
||||
# only that we're not treating the telemetry.uuid file correctly
|
||||
|
||||
function Get-OSTelemetryLevel {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns the effective Windows Telemetry level (0-3).
|
||||
Logic: Checks GPO overrides, then System preferences, then defaults to 1.
|
||||
#>
|
||||
|
||||
$gpoPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection"
|
||||
$sysPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection"
|
||||
$valueName = "AllowTelemetry"
|
||||
|
||||
# 1. Check the "Managed" Policy (Group Policy)
|
||||
if (Test-Path $gpoPath) {
|
||||
$gpoValue = Get-ItemProperty -Path $gpoPath -Name $valueName -ErrorAction SilentlyContinue
|
||||
if ($gpoValue -and $gpoValue.$valueName) {
|
||||
return [int]$gpoValue.$valueName
|
||||
}
|
||||
}
|
||||
|
||||
# 2. Check the "User/System" Preference (Settings App)
|
||||
if (Test-Path $sysPath) {
|
||||
$sysValue = Get-ItemProperty -Path $sysPath -Name $valueName -ErrorAction SilentlyContinue
|
||||
if ($sysValue -and $sysValue.$valueName) {
|
||||
return [int]$sysValue.$valueName
|
||||
}
|
||||
}
|
||||
|
||||
# 3. Fallback to OS Default (Basic/Required)
|
||||
return 1
|
||||
}
|
||||
|
||||
Describe "Telemetry for shell startup" -Tag CI {
|
||||
BeforeAll {
|
||||
$skipTelemetryTests = $false
|
||||
|
||||
if ($IsWindows) {
|
||||
## Skip telemetry tests if the OS telemetry level is less than 2 (Enhanced) -- PS telemetry is disabled in this case.
|
||||
$osTelemetryLevel = Get-OSTelemetryLevel
|
||||
$skipTelemetryTests = $osTelemetryLevel -lt 2
|
||||
}
|
||||
|
||||
if ($skipTelemetryTests) {
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
return
|
||||
}
|
||||
|
||||
# if the telemetry file exists, move it out of the way
|
||||
# the member is internal, but we can retrieve it via reflection
|
||||
$cacheDir = [System.Management.Automation.Platform].GetField("CacheDirectory","NonPublic,Static").GetValue($null)
|
||||
@@ -23,6 +68,11 @@ Describe "Telemetry for shell startup" -Tag CI {
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
if ($skipTelemetryTests) {
|
||||
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
return
|
||||
}
|
||||
|
||||
# check and reset the telemetry.uuid file
|
||||
if ( $uuidFileExists ) {
|
||||
if ( Test-Path -Path "${uuidPath}.original" ) {
|
||||
|
||||
Reference in New Issue
Block a user