Home > Blockchain >  'Get-WindowsDriver' is not recognized as the name of a cmdlet
'Get-WindowsDriver' is not recognized as the name of a cmdlet

Time:10-09

I'm developing under .NET Framework 4.8. Note that I'm strictly locked to use .NET 4.8.

I've installed the "Microsoft.PowerShell.5.1.ReferenceAssemblies" Nuget package in order to be able automate Powershell commands, since the Nuget packages for PS6 and PS7 reuquires .net core at least.

The problem is that I'm unable to run the enter image description here

Create a new project: Windows Forms App (.NET Framework)

Download/install NuGet package:

Since you're using .NET Framework 4.8 and PowerShell v5.1, download/install NuGet package: Microsoft.PowerShell.5.1.ReferenceAssemblies

See Choosing the right PowerShell NuGet package for your .NET project for more information.

Add the following using directives:

  • Imports System.Management.Automation
  • Imports System.Management.Automation.Runspaces
  • Imports Microsoft.PowerShell

Then use one of the following:

Public Function PSGetModule() As String

    Dim sb As System.Text.StringBuilder = New System.Text.StringBuilder()

    'create the default initial session state.
    Dim sessionState As InitialSessionState = InitialSessionState.CreateDefault()

    sessionState.ExecutionPolicy = ExecutionPolicy.Unrestricted
    sessionState.ImportPSModule({"C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Dism\Dism.psd1"})
    'sessionState.ImportPSModule({"C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Dism"})

    Using ps As PowerShell = PowerShell.Create(sessionState)
        Dim results As ObjectModel.Collection(Of PSObject) = ps.AddCommand("Get-Module").Invoke()
        'Dim results As ObjectModel.Collection(Of PSObject) = ps.AddScript("Get-Module").Invoke()

        For Each result As PSObject In results
            sb.AppendLine(result.ToString())
        Next
    End Using

    Return sb.ToString()
End Function

Public Function PSGetModule2() As String
    Debug.WriteLine($"PSGetModule2")

    Dim sb As System.Text.StringBuilder = New System.Text.StringBuilder()

    'create the default initial session state.
    Dim sessionState As InitialSessionState = InitialSessionState.CreateDefault()

    sessionState.ExecutionPolicy = ExecutionPolicy.Unrestricted
    sessionState.ImportPSModule({"C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Dism\Dism.psd1"})
    'sessionState.ImportPSModule({"C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Dism"})

    Using rs As Runspace = RunspaceFactory.CreateRunspace(sessionState)
        'open
        rs.Open()

        Using ps As PowerShell = PowerShell.Create()
            ps.Runspace = rs

            Dim results As ObjectModel.Collection(Of PSObject) = ps.AddCommand("Get-Module").Invoke()

            For Each result As PSObject In results
                sb.AppendLine(result.ToString())
            Next
        End Using
    End Using

    Return sb.ToString()
End Function

Public Async Function PSGetModuleAsync() As Task(Of String)
    Dim sb As System.Text.StringBuilder = New System.Text.StringBuilder()

    'create the default initial session state.
    Dim sessionState As InitialSessionState = InitialSessionState.CreateDefault()
    sessionState.ExecutionPolicy = ExecutionPolicy.Unrestricted
    sessionState.ImportPSModule({"C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Dism\Dism.psd1"})
    'sessionState.ImportPSModule({"C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Dism"})

    Using ps As PowerShell = PowerShell.Create(sessionState)
        ps.AddCommand("Get-Module")

        Dim results = Await Task.Factory.FromAsync(ps.BeginInvoke(), Function(asyncResult As IAsyncResult) ps.EndInvoke(asyncResult))

        For Each result As PSObject In results
            sb.AppendLine(result.ToString())
        Next
    End Using

    Return sb.ToString()
End Function

Usage:

Dim result As String = PSGetModule()
Debug.WriteLine($"result (PSGetModule): {result}")

Usage (Async)

Dim result As String = Await PSGetModuleAsync()
Debug.WriteLine($"result: {result}")

I was able to execute Get-WindowsDriver, using code from this post. Here's the method that I used for testing (you may wish to change it to a function):

Public Sub GetSystemDrivers(flags As GetDriverFlags)
    'create the default initial session state.
    Dim sessionState As InitialSessionState = InitialSessionState.CreateDefault()
    sessionState.ExecutionPolicy = ExecutionPolicy.Unrestricted
    'sessionState.ImportPSModule("Dism")

    'create a runspace. using the default host
    Using rs As Runspace = RunspaceFactory.CreateRunspace(sessionState)
        'open
        rs.Open()

        Dim hasFlagInbox As Boolean = flags.HasFlag(GetDriverFlags.Inbox)
        Dim hasFlagNotInbox As Boolean = flags.HasFlag(GetDriverFlags.NotInbox)

        'set value
        Runspace.DefaultRunspace = rs

        Using ps As PowerShell = PowerShell.Create()

            ps.Runspace = rs

            Dim dismDriverObjects = ps.AddCommand("Get-WindowsDriver").AddParameter("Online").Invoke()

            For Each dismDriverObject As PSObject In dismDriverObjects
                'create new instance
                Dim driverInfo As New DismDriverInfo(dismDriverObject)

                If flags <> GetDriverFlags.Any Then
                    If (hasFlagInbox AndAlso Not driverInfo.Inbox) OrElse
                   (hasFlagNotInbox AndAlso driverInfo.Inbox) Then
                        Continue For
                    End If
                End If

                Debug.WriteLine($"Driver: {driverInfo.DriverFile}")
                Debug.WriteLine($"Date: {driverInfo.BuildDate}")
                Debug.WriteLine($"Version: {driverInfo.Version}")
            Next
        End Using
    End Using
End Sub

Note: Since Get-WindowsDriver requires administrative privileges, add an Application Manifest File (Project => Add New Item... => Application Manifest File) to your project. Then change from <requestedExecutionLevel level="asInvoker" uiAccess="false" /> to <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />.

Resources:

CodePudding user response:

I found that the problem is related to missing dependencies for some processor architectures, related to DISM. I'm on Windows 10 x64 so my PowerShell automation code based on DISM / Get-WindowsDriver cmdlet will only run successful (without exceptions) when compiling my application to x64.

The problem is that I was compiling to "AnyCPU", and that is why PowerShell was not able to find DISM module and it was throwing that exception. Don't ask me if this architecture issue is normal, but that was the root of the problem, and it throws the same exception when targeting x86 architecture. So the solution is to compile for x64.


I just will share for the record this generic usage function that I used to run Get-Module cmdlet to ensure that DISM module is loaded:

<DebuggerStepThrough>
Public Shared Function ExecutePowerShellScript(script As String, ParamArray importModules As String()) As Collection(Of PSObject)

    Dim sessionState As InitialSessionState = InitialSessionState.CreateDefault()
    sessionState.ExecutionPolicy = ExecutionPolicy.Unrestricted
    sessionState.ImportPSModule(importModules)

    Dim results As Collection(Of PSObject)
    Dim errors As PSDataCollection(Of ErrorRecord)

    Using runspace As Runspace = RunspaceFactory.CreateRunspace(sessionState)

        ' Save current default runspace, if any.
        Dim previousDefaultRunSpace As Runspace = Runspace.DefaultRunspace

        ' By using this custom default runspace on which we have specified "ExecutionPolicy.Unrestricted" policy, 
        ' we ensure that PowerShell don't run on new/different threads that can have restricted execution policies,
        ' otherwise it will throw an exception due the restriction policy. 
        Runspace.DefaultRunspace = runspace
        Runspace.DefaultRunspace.Open()

        Using ps As PowerShell = PowerShell.Create(RunspaceMode.CurrentRunspace)

            ps.AddScript(script)

            Try
                results = ps.Invoke()

                ' The PowerShell environment has a "PowerShell.HadErrors" property 
                ' that indicates in the assumption whether errors have occurred.
                ' Unfortunately, most often, I have found that despite errors
                ' its value can be "False", and vice versa, I have found that 
                ' in the absence of errors its value can be "True".

                ' Therefore, we check the fact that errors have occurred, 
                ' using the error counter in "PowerShell.Streams" property:
                If ps.Streams.Error.Any() Then
                    errors = New PSDataCollection(Of ErrorRecord)()
                    Throw errors.First().Exception
                End If

            Catch ex As Exception
                Throw

            End Try

            Runspace.DefaultRunspace.Close()

            ' Restore previous default runspace, if any.
            Runspace.DefaultRunspace = previousDefaultRunSpace

        End Using

    End Using

    Return results

End Function

Example Usage:

Dim importModules As String() = {"Dism", "PSReadline", "WindowsSearch"}
Dim script As String = "Get-Module | Format-Table -Property Name, Version, Moduletype | Out-String"

Dim results As Collection(Of PSObject) = ExecutePowerShellScript(script, importModules)
Debug.WriteLine(results.Single().ToString())
  • Related