Skip to content

Commit 7ddfb82

Browse files
SteveL-MSFTTravisEz13
authored andcommitted
Add back Get-Counter cmdlet for Windows (PowerShell#10933)
1 parent 518a479 commit 7ddfb82

File tree

8 files changed

+102
-485
lines changed

8 files changed

+102
-485
lines changed

src/Microsoft.PowerShell.Commands.Diagnostics/CommonUtils.cs

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,90 @@ namespace Microsoft.PowerShell.Commands.Diagnostics.Common
1414
{
1515
internal static class CommonUtilities
1616
{
17+
private const string LibraryLoadDllName = "api-ms-win-core-libraryloader-l1-2-0.dll";
18+
private const string LocalizationDllName = "api-ms-win-core-localization-l1-2-1.dll";
19+
20+
private const uint FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
21+
private const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
22+
private const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
23+
private const uint FORMAT_MESSAGE_FROM_HMODULE = 0x00000800;
24+
25+
[DllImport(LocalizationDllName, SetLastError = true, CharSet = CharSet.Unicode)]
26+
private static extern uint FormatMessage(uint dwFlags, IntPtr lpSource,
27+
uint dwMessageId, uint dwLanguageId,
28+
[MarshalAs(UnmanagedType.LPWStr)]
29+
StringBuilder lpBuffer,
30+
uint nSize, IntPtr Arguments);
31+
32+
[DllImport(LibraryLoadDllName, SetLastError = true, CharSet = CharSet.Unicode)]
33+
private static extern IntPtr LoadLibraryEx(
34+
[MarshalAs(UnmanagedType.LPWStr)] string lpFileName,
35+
IntPtr hFile,
36+
uint dwFlags
37+
);
38+
39+
[DllImport(LibraryLoadDllName)]
40+
private static extern bool FreeLibrary(IntPtr hModule);
41+
42+
43+
[DllImport(LocalizationDllName, EntryPoint = "GetUserDefaultLangID", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
44+
private static extern ushort GetUserDefaultLangID();
45+
46+
47+
public static uint FormatMessageFromModule(uint lastError, string moduleName, out String msg)
48+
{
49+
Debug.Assert(!string.IsNullOrEmpty(moduleName));
50+
51+
uint formatError = 0;
52+
msg = String.Empty;
53+
54+
IntPtr moduleHandle = LoadLibraryEx(moduleName, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
55+
if (moduleHandle == IntPtr.Zero)
56+
{
57+
return (uint)Marshal.GetLastWin32Error();
58+
}
59+
60+
try
61+
{
62+
uint dwFormatFlags = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE;
63+
uint LANGID = (uint)GetUserDefaultLangID();
64+
uint langError = (uint)Marshal.GetLastWin32Error();
65+
if (langError != 0)
66+
{
67+
LANGID = 0; // neutral
68+
}
69+
70+
StringBuilder outStringBuilder = new StringBuilder(1024);
71+
uint nChars = FormatMessage(dwFormatFlags,
72+
moduleHandle,
73+
lastError,
74+
LANGID,
75+
outStringBuilder,
76+
(uint)outStringBuilder.Capacity,
77+
IntPtr.Zero);
78+
79+
if (nChars == 0)
80+
{
81+
formatError = (uint)Marshal.GetLastWin32Error();
82+
}
83+
else
84+
{
85+
msg = outStringBuilder.ToString();
86+
if (msg.EndsWith(Environment.NewLine, StringComparison.Ordinal))
87+
{
88+
msg = msg.Substring(0, msg.Length - 2);
89+
}
90+
}
91+
}
92+
finally
93+
{
94+
FreeLibrary(moduleHandle);
95+
}
96+
return formatError;
97+
}
98+
1799
public static ResourceManager GetResourceManager()
18100
{
19-
// this naming pattern is dictated by the dotnet cli
20101
return new ResourceManager("Microsoft.PowerShell.Commands.Diagnostics.resources.GetEventResources", typeof(CommonUtilities).GetTypeInfo().Assembly);
21102
}
22103
}

src/Microsoft.PowerShell.Commands.Diagnostics/GetCounterCommand.cs

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace Microsoft.PowerShell.Commands
3131
///
3232
/// Class that implements the Get-Counter cmdlet.
3333
///
34-
[Cmdlet(VerbsCommon.Get, "Counter", DefaultParameterSetName = "GetCounterSet", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=138335")]
34+
[Cmdlet(VerbsCommon.Get, "Counter", DefaultParameterSetName = "GetCounterSet", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2109647")]
3535
public sealed class GetCounterCommand : PSCmdlet
3636
{
3737
//
@@ -211,19 +211,13 @@ public string[] ComputerName
211211
protected override void BeginProcessing()
212212
{
213213

214-
#if CORECLR
215214
if (Platform.IsIoT)
216215
{
217216
// IoT does not have the '$env:windir\System32\pdh.dll' assembly which is required by this cmdlet.
218217
throw new PlatformNotSupportedException();
219218
}
220219

221-
// PowerShell 7 requires at least Windows 7,
222-
// so no version test is needed
223-
_pdhHelper = new PdhHelper(false);
224-
#else
225-
_pdhHelper = new PdhHelper(System.Environment.OSVersion.Version.Major < 6);
226-
#endif
220+
_pdhHelper = new PdhHelper();
227221
_resourceMgr = Microsoft.PowerShell.Commands.Diagnostics.Common.CommonUtilities.GetResourceManager();
228222

229223
uint res = _pdhHelper.ConnectToDataSource();
@@ -570,12 +564,7 @@ private void ProcessGetCounter()
570564
break;
571565
}
572566

573-
#if CORECLR
574-
// CoreCLR has no overload of WaitOne with (interval, exitContext)
575-
bool cancelled = _cancelEventArrived.WaitOne((int)_sampleInterval * 1000);
576-
#else
577567
bool cancelled = _cancelEventArrived.WaitOne((int)_sampleInterval * 1000, true);
578-
#endif
579568
if (cancelled)
580569
{
581570
break;
@@ -666,11 +655,7 @@ private void WriteSampleSetObject(PerformanceCounterSampleSet set)
666655

667656
private static CultureInfo GetCurrentCulture()
668657
{
669-
#if CORECLR
670-
return CultureInfo.CurrentCulture;
671-
#else
672658
return Thread.CurrentThread.CurrentUICulture;
673-
#endif
674659
}
675660
}
676661
}

src/Microsoft.PowerShell.Commands.Diagnostics/Microsoft.PowerShell.Commands.Diagnostics.csproj

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,19 @@
1515
</PropertyGroup>
1616

1717
<ItemGroup>
18+
<Compile Remove="GetEventSnapin.cs" />
19+
<Compile Remove="ExportCounterCommand.cs" />
20+
<Compile Remove="ImportCounterCommand.cs" />
1821
<Compile Remove="CounterFileInfo.cs" />
22+
</ItemGroup>
23+
24+
<ItemGroup Condition=" '$(IsWindows)' != 'true' ">
25+
<Compile Remove="GetCounterCommand.cs" />
1926
<Compile Remove="CounterSample.cs" />
2027
<Compile Remove="CounterSet.cs" />
21-
<Compile Remove="ExportCounterCommand.cs" />
22-
<Compile Remove="GetCounterCommand.cs" />
23-
<Compile Remove="GetEventSnapin.cs" />
24-
<Compile Remove="ImportCounterCommand.cs" />
2528
<Compile Remove="PdhHelper.cs" />
2629
<Compile Remove="PdhSafeHandle.cs" />
2730
<Compile Remove="gen\GetEventResources.cs" />
28-
</ItemGroup>
29-
30-
<ItemGroup Condition=" '$(IsWindows)' != 'true' ">
3131
<Compile Remove="GetEventCommand.cs" />
3232
<Compile Remove="NewWinEventCommand.cs" />
3333
</ItemGroup>

0 commit comments

Comments
 (0)