1

I'm trying to get the uptime of the system in ticks. I want to use a 64 bit method specifically to avoid the wrap-around that happens under the 32 bit version. I know there are other ways to see an uptime but I'm not using those as they cause other issues for my implementation.

I'm trying to use GetTickCount64() from Kernel32.dll as this should give me what I want.

$MethodDefinition = @"
[DllImport("kernel32")] extern static UInt64 GetTickCount64();
"@

$Kernel32 = Add-Type -MemberDefinition $MethodDefinition -Name 'Kernel32' -Namespace 'Win32' -PassThru

$Kernel32::GetTickCount64()

Unfortunately running this code gives me the following error:

WARNING: The generated type defines no public methods or properties.
Method invocation failed because [Win32.Kernel32] does not contain a method named 'GetTickCount64'.

I don't understand why this doesn't work on Windows 10, this method has been available since Vista.

Why can't this method be located?

Equalsk
  • 7,954
  • 2
  • 41
  • 67
  • 3
    update method def to `[DllImport("kernel32")] public extern static UInt64 GetTickCount64();` (notice the `publice` access modifier in front of `extern`) – Mathias R. Jessen Aug 17 '20 at 14:28
  • @MathiasR.Jessen Well I feel stupid. Please can you make this an answer and I'll accept when I can? Thank you. – Equalsk Aug 17 '20 at 14:29
  • Ahh didn't see this. I guess it don't matter if extern or static is listed first - either worked for me. – Doug Maurer Aug 17 '20 at 14:33
  • 1
    @DougMaurer Yeah, from a syntactical point of view the `public`, `extern`, and `static` keywords are all [modifiers in this context](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes#methods), you can specify them in any order you like – Mathias R. Jessen Aug 17 '20 at 14:37
  • Thanks @iiresetme - btw, you're awesome! Still waiting on that pscache talk.. you know, the one that ran out of time. Did you end up doing it again anywhere? – Doug Maurer Aug 17 '20 at 14:39
  • @DougMaurer Hehehe, yes I did manage to [publish a preview version](https://www.powershellgallery.com/packages/PSCache/0.1.1-alpha1) with some of the new eviction policies, more details on GitHub if you're interested. Hit me up on Twitter or file a GH issue if you have any features in mind :) – Mathias R. Jessen Aug 17 '20 at 14:44

2 Answers2

4

If you omit an explicit access modifier in a C# method signature, it defaults to private, meaning you won't be able to invoke the method via $Kernel32::GetTickCount64(), hence the warning.

Fixing it is easy, simple supply the public access modifier explicitly:

$MethodDefinition = @"
[DllImport("kernel32")]
public extern static UInt64 GetTickCount64();
"@

(I find these import signatures easier to read when the DllImport attribute sits above, no functional difference)

Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
3

Mark the method as public, this should work

$MethodDefinition = @"
[DllImport("kernel32")] public static extern UInt64 GetTickCount64();
"@

$Kernel32 = Add-Type -MemberDefinition $MethodDefinition -Name 'Kernel32' -Namespace 'Win32' -PassThru

$Kernel32::GetTickCount64()

Output

4059006625
Doug Maurer
  • 8,090
  • 3
  • 12
  • 13