For the last 6months or so I have been messing around with PowerShell. A bit saddened to learn it was the last update by Microsoft but that is life.

I have got tired with WMI. Since Windows 10 a lot has stopped working for me as a simple restore point. Regarding WMI vs Powershell, the main people say "Avoid using WMI at all". However, it should be noted these cmdlets are simply wrapped and that the underlying technology is still WMI.

I thought I would share a few features I currently use in VB for learning and simplicity sake. I am not stating you should use these over framework methods.

1) InvokeExpression: Obtain information etc https://docs.microsoft.com/en-us/pow...w=powershell-6

2) System restore

3) Detect the status of windows ransomware

4) Get-CimInstance https://docs.microsoft.com/en-us/pow...w=powershell-6

5) GetAuthenticodeSignature of a single file.

6) GetAuthenticodeSignature() of a collection of files

7) GetFileHash() Gets theMD5 or SHA256 file hash.

8) Turns system restore ON

Please note this was stripped from One of my current projects so you will need to adjust some lines.

vb Code:
  1. Imports System.Collections.ObjectModel
  2. Imports System.IO
  3. Imports System.Management.Automation
  4. Imports System.Text.RegularExpressions
  5. Imports Powershell.Classes.Interface
  6. Imports Powershell.Classes.Properties
  7.  
  8. Namespace Classes
  9.     ''' <summary>
  10.     '''     Responsible for handling all lightweight commands that are used in the PowerShell class.
  11.     ''' </summary>
  12.     Friend Class PowerShellInvoker
  13.         Implements IPowershell
  14.  
  15.         ''' <summary>
  16.         '''     The EnableControlledFolderAccess regular expression pattern.
  17.         ''' </summary>
  18.         Private Const MRansomewarePattern As String = "^@{EnableControlledFolderAccess=1}$"
  19.  
  20.         ''' <summary>
  21.         '''     The EnableControlledFolderAccess regular expression instance.
  22.         ''' </summary>
  23.         Private ReadOnly _mRansomewareMatch As New Regex(MRansomewarePattern, RegexOptions.Compiled)
  24.  
  25.         ''' <summary>
  26.         '''     Runs commands or expressions on the local computer.
  27.         ''' </summary>
  28.         ''' <param name="command">
  29.         '''     The Command parameter to specify the command to run.
  30.         ''' </param>
  31.         ''' <param name="member">
  32.         '''     The Propertie name from the Invoke-Expression instances.
  33.         ''' </param>
  34.         ''' <returns>
  35.         '''     Returns the output that is generated by the invoked command (the value of the Command parameter).
  36.         ''' </returns>
  37.         ''' <remarks>
  38.         '''     The Invoke-Expression cmdlet evaluates or runs a specified string as a command and returns the results of the
  39.         '''     expression
  40.         '''     or command. Without Invoke-Expression, a string submitted at the command line would be returned (echoed) unchanged.
  41.         '''     See
  42.         '''     [url]https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-expression?view=powershell-6[/url]
  43.         ''' </remarks>
  44.         Friend Function InvokeExpression(command As String, Optional member As String = "") As String
  45.             Dim scriptText As String = $"Invoke-Expression -Command {command}"
  46.             Dim results As Results = ExecuteCmdlet(scriptText)
  47.             Dim psObject As Collection(Of PSObject) = results.PowerShellObject
  48.             Dim errors As IList = results.ListErrors
  49.             Dim message = ""
  50.  
  51.             If errors IsNot Nothing AndAlso errors.Count > 0 Then
  52.                 message = (errors.Cast(Of PSObject).First.ToString)
  53.             Else
  54.                 message = psObject.Select(Function(n) $"{n.Members($"{member}").Value}").First.ToString
  55.             End If
  56.  
  57.             Return message
  58.         End Function
  59.  
  60.         ''' <summary>
  61.         '''     Creates a system restore point on the local computer.
  62.         ''' </summary>
  63.         ''' <returns>
  64.         '''     A successful message if no errors have been found.
  65.         ''' </returns>
  66.         ''' <remarks>
  67.         '''     The Checkpoint-Computer cmdlet creates a system restore point on the local computer.
  68.         '''     See
  69.         '''     [url]https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/checkpoint-computer?view=powershell-5.1[/url]
  70.         ''' </remarks>
  71.         Friend Function CheckpointComputer() As List(Of String)
  72.             Dim checkStamp As String = $"{"insert app name"}#{Now}"
  73.             Dim messages As New List(Of String)
  74.             Dim scriptText As String = $"Checkpoint-Computer -Description ""{checkStamp}"" -RestorePointType MODIFY_SETTINGS"
  75.             CheckpointComputerEnable()
  76.  
  77.             Dim results As Results = ExecuteCmdlet(scriptText)
  78.             Dim errors As IList = results.ListErrors
  79.  
  80.             If errors IsNot Nothing AndAlso errors.Count > 0 Then
  81.                 messages.Add(errors.Cast(Of PSObject).First.ToString)
  82.             Else
  83.                 messages.Add($"{"add message was here"} Checkpoint-{checkStamp}")
  84.             End If
  85.  
  86.             Return messages
  87.         End Function
  88.  
  89.         ''' <summary>
  90.         '''     Windows Defender Advanced Threat Protection (Windows Defender ATP)
  91.         ''' </summary>
  92.         ''' <returns>
  93.         '''     The audit modes current state.
  94.         ''' </returns>
  95.         ''' <remarks>
  96.         '''     See [url]https://docs.microsoft.com/en-us/powershell/module/defender/get-mppreference?view=win10-ps[/url]
  97.         '''     And also
  98.         '''     [url]https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-defender-exploit-guard/evaluate-controlled-folder-accesss[/url]
  99.         ''' </remarks>
  100.         Friend Function DefenderAdvancedThreatProtectionIsEnabled() As List(Of String)
  101.             Const scriptText = "get-MpPreference | select-object -property EnableControlledFolderAccess"
  102.  
  103.             Dim results As Results = ExecuteCmdlet(scriptText)
  104.             Dim messages As New List(Of String) From {String.Empty}
  105.             Dim psObject As Collection(Of PSObject) = results.PowerShellObject
  106.             Dim errors As IList = results.ListErrors
  107.             Dim item = psObject.FirstOrDefault()
  108.  
  109.             If errors IsNot Nothing AndAlso errors.Count > 0 Then
  110.                 messages.Add(errors.Cast(Of PSObject).First.ToString)
  111.             Else
  112.                 If _mRansomewareMatch.IsMatch(item.ToString) Then
  113.                     messages.Add("add message here")
  114.                 End If
  115.             End If
  116.  
  117.             Return messages
  118.         End Function
  119.  
  120.         ''' <summary>
  121.         '''     Gets the CIM instances of a class from a CIM server.
  122.         '''     The Win32_OperatingSystem WMI class represents a Windows-based operating system
  123.         '''     installed on a computer.
  124.         ''' </summary>
  125.         ''' <param name="member">
  126.         '''     The Propertie name from the CIM instances of a class named Win32_OperatingSystem.
  127.         ''' </param>
  128.         ''' <returns>
  129.         '''     The cmdlet returns one or more CIM instance objects representing a snapshot of the CIM
  130.         '''     instances present on the CIM server.
  131.         ''' </returns>
  132.         ''' <remarks>
  133.         '''     See [url]https://docs.microsoft.com/en-us/powershell/module/cimcmdlets/get-ciminstance?view=powershell-6[/url]
  134.         '''     And also [url]https://docs.microsoft.com/en-us/windows/desktop/cimwin32prov/win32-operatingsystem[/url]
  135.         ''' </remarks>
  136.         Friend Function GetCimInstance(member As String) As String
  137.             Dim scriptText As String = $"Get-CimInstance Win32_OperatingSystem | Select-Object {member}"
  138.             Dim results As Results = ExecuteCmdlet(scriptText)
  139.             Dim psObject As Collection(Of PSObject) = results.PowerShellObject
  140.             Dim errors As IList = results.ListErrors
  141.             Dim message As String
  142.  
  143.             If errors IsNot Nothing AndAlso errors.Count > 0 Then
  144.                 message = (errors.Cast(Of PSObject).First.ToString)
  145.             Else
  146.                 message = psObject.Select(Function(n) $"{n.Members($"{member}").Value}").First.ToString
  147.             End If
  148.  
  149.             Return message
  150.         End Function
  151.  
  152.         ''' <summary>
  153.         '''     Gets information about the Authenticode signature for a file.
  154.         ''' </summary>
  155.         ''' <param name="filePath">
  156.         '''     Specifies the path to the file to examine.
  157.         ''' </param>
  158.         ''' <returns>
  159.         '''     The information about the Authenticode signature.
  160.         ''' </returns>
  161.         ''' <remarks>
  162.         '''     The Get-AuthenticodeSignature cmdlet gets information about the Authenticode signature for a file. If the
  163.         '''     file is not signed, the information is retrieved, but the fields are blank.
  164.         '''     See
  165.         '''     [url]https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/get-authenticodesignature?view=powershell-6[/url]
  166.         ''' </remarks>
  167.         Friend Function GetAuthenticodeSignature(filePath As String) As String
  168.             Dim scriptText As String = $"Get-AuthenticodeSignature -FilePath ""{filePath}"""
  169.             Dim results As Results = ExecuteCmdlet(scriptText)
  170.             Dim psObject As Collection(Of PSObject) = results.PowerShellObject
  171.             Dim errors As IList = results.ListErrors
  172.             Dim message As String
  173.  
  174.             If errors IsNot Nothing AndAlso errors.Count > 0 Then
  175.                 message = (errors.Cast(Of PSObject).First.ToString)
  176.             Else
  177.                 message = psObject.Select(Function(n) $"{n.Members("Path").Value} {n.Members("StatusMessage").Value}").First.ToString()
  178.             End If
  179.  
  180.             Return message
  181.         End Function
  182.  
  183.         ''' <summary>
  184.         '''     Gets information about the Authenticode signature for a file.
  185.         ''' </summary>
  186.         ''' <returns>
  187.         '''     The information about the Authenticode signature.
  188.         ''' </returns>
  189.         ''' <remarks>
  190.         '''     The Get-AuthenticodeSignature cmdlet gets information about the Authenticode signature for a file. If the
  191.         '''     file is not signed, the information is retrieved, but the fields are blank.
  192.         '''     See
  193.         '''     [url]https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/get-authenticodesignature?view=powershell-6[/url]
  194.         ''' </remarks>
  195.         Friend Function GetAuthenticodeSignature() As List(Of String)
  196.             Const scriptText = "$input | ForEach-object {Get-AuthenticodeSignature $_}"
  197.  
  198.             Dim file = "my file of white listed"
  199.             Dim messages As New List(Of String)
  200.             Dim files As String() = Regex.Split(file, Environment.NewLine).Select(Function(l) Path.Combine(WindowsPathValue, l)).ToArray
  201.             Dim results As Results = ExecuteCmdlet(scriptText, files)
  202.             Dim psObject As Collection(Of PSObject) = results.PowerShellObject
  203.             Dim errors As IList = results.ListErrors
  204.  
  205.             If errors IsNot Nothing AndAlso errors.Count > 0 Then
  206.                 messages.Add(errors.Cast(Of PSObject).First.ToString)
  207.             Else
  208.                 messages.AddRange(From result In psObject Select $"{result.Members("Path").Value} {result.Members("StatusMessage").Value}")
  209.             End If
  210.  
  211.             Return messages
  212.         End Function
  213.  
  214.         ''' <summary>
  215.         '''     Computes the hash value for a file by using a specified hash algorithm.
  216.         ''' </summary>
  217.         ''' <param name="file">
  218.         '''     Specifies the path to one or more files as an array. Wild card characters are permitted.
  219.         ''' </param>
  220.         ''' <param name="algorithm">
  221.         '''     Specifies the cryptographic hash function to use for computing the hash value of the
  222.         '''     contents of the specified file.
  223.         ''' </param>
  224.         ''' <returns>
  225.         '''     The Get-FileHash cmdlet computes the hash value for a file by using a specified hash algorithm.
  226.         ''' </returns>
  227.         ''' <remarks>
  228.         '''     By default, the Get-FileHash cmdlet uses the SHA256 algorithm,
  229.         '''     See [url]https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-filehash?view=powershell-6[/url]
  230.         ''' </remarks>
  231.         Friend Function GetFileHash(file As String, Optional algorithm As String = "SHA256") As String
  232.             Dim scriptText As String = $"Get-FileHash ""{file}"" -Algorithm {algorithm}"
  233.             Dim results As Results = ExecuteCmdlet(scriptText)
  234.             Dim psObject As Collection(Of PSObject) = results.PowerShellObject
  235.             Dim errors As IList = results.ListErrors
  236.             Dim message As String
  237.  
  238.             If errors IsNot Nothing AndAlso errors.Count > 0 Then
  239.                 message = (errors.Cast(Of PSObject).First.ToString)
  240.             Else
  241.                 message = psObject.Select(Function(n) n.Members("Hash").Value).First.ToString
  242.             End If
  243.  
  244.             Return message
  245.         End Function
  246.  
  247.         ''' <summary>
  248.         '''     Attempts to enable system restore on the specified drive.
  249.         ''' </summary>
  250.         ''' <remarks>
  251.         '''     There is no output for this method.
  252.         '''     See
  253.         '''     [url]https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/enable-computerrestore?view=powershell-5.1[/url]
  254.         ''' </remarks>
  255.         Private Sub CheckpointComputerEnable()
  256.             Dim scriptText As String = $"Enable-ComputerRestore -Drive ""{WindowsRootPathValue}"""
  257.             ExecuteCmdlet(scriptText)
  258.         End Sub
  259.  
  260.         ''' <summary>
  261.         '''     Executes power shell scripts.
  262.         ''' </summary>
  263.         ''' <param name="scriptText">
  264.         '''     The power shell script text.
  265.         ''' </param>
  266.         ''' <param name="scriptOptions">
  267.         '''     Optional commands to include to the power shell script.
  268.         ''' </param>
  269.         ''' <returns>
  270.         '''     A collection of PSObject to obtain the PSMemberInfoCollection if exists. The IList exceptions if exist.
  271.         ''' </returns>
  272.         ''' <remarks>
  273.         '''     See [url]https://docs.microsoft.com/en-us/powershell/developer/cmdlet/cmdlet-overview[/url]
  274.         ''' </remarks>
  275.         Private Function ExecuteCmdlet(scriptText As String, Optional scriptOptions As String() = Nothing) As Results _
  276.             Implements IPowershell.ExecuteCmdlet
  277.             Dim text As String = scriptText
  278.             Dim options As String() = scriptOptions
  279.             Dim errors As IList = Nothing
  280.             Dim query = New RunspaceInvoke().Invoke(text, options, errors)
  281.  
  282.             Return New Results(query, errors)
  283.         End Function
  284.     End Class
  285. End Namespace

for completeness sake:

Interface
vb Code:
  1. Imports Powershell.Classes.Properties
  2.  
  3. Namespace Classes.Interface
  4.     ''' <summary>
  5.     '''     The Interface for classes that require the implementation IPowershell.
  6.     ''' </summary>
  7.     Public Interface IPowershell
  8.         ''' <summary>
  9.         '''     Executes powershell scripts.
  10.         ''' </summary>
  11.         ''' <param name="scriptText">
  12.         '''     The power shell script text.
  13.         ''' </param>
  14.         ''' <param name="scriptOptions">
  15.         '''     Optional commands to include in the powershell script.
  16.         ''' </param>
  17.         ''' <returns>
  18.         '''     A collection of PSObject to obtain the PSMemberInfoCollection if exists. The IList exceptions if exist.
  19.         ''' </returns>
  20.         Function ExecuteCmdlet(scriptText As String, Optional scriptOptions As String() = Nothing) As Results
  21.     End Interface
  22. End Namespace

Properties
vb Code:
  1. Imports System.Collections.ObjectModel
  2. Imports System.Management.Automation
  3.  
  4. Namespace Classes.Properties
  5.     ''' <summary>
  6.     '''     Responsible for returning the results from the <see cref="PowerShellInvoker">PowerShellInvoker</see> class.
  7.     ''' </summary>
  8.     Public Class Results
  9.         ''' <summary>
  10.         '''     Responsible for knowing the initializes new instance of the PSObject class.
  11.         ''' </summary>
  12.         ''' <returns>
  13.         '''     A new instance of the PSObject class.
  14.         ''' </returns>
  15.         Friend ReadOnly Property PowerShellObject As Collection(Of PSObject)
  16.  
  17.         ''' <summary>
  18.         '''     A non-generic collection of objects to represent the PSObject errors.
  19.         ''' </summary>
  20.         ''' <returns>
  21.         '''     A non-generic object collection of errors cmdlet errors.
  22.         ''' </returns>
  23.         Friend ReadOnly Property ListErrors As IList
  24.  
  25.         ''' <summary>
  26.         '''     Creates a new instance of the <see cref="Results" /> Class.
  27.         ''' </summary>
  28.         ''' <param name="pShellObject">
  29.         '''     The power shell object instance.
  30.         ''' </param>
  31.         ''' <param name="lErrors">
  32.         '''     The IList errors interface instance.
  33.         ''' </param>
  34.         Friend Sub New(pShellObject As Collection(Of PSObject), lErrors As IList)
  35.             PowerShellObject = pShellObject
  36.             ListErrors = lErrors
  37.         End Sub
  38.     End Class
  39. End Namespace