none
Problems getting code working with Option Strict On

    Question

  • Hi

    I have the following code which works perfectly with Option Strict Off - but an app I want to add it to has Option Strict On and I would prefer to leave it on if possible, so how can I get code working with Option Strict On?

    There seems to be two different errors I need to work round

    1) option strict on disallows operands of type object for operator '='    on line " If OutParams("DefragRecommended") = True" which I have managed to fix using

    DimDefragRequired AsString= OutParams("DefragRecommended").ToString

    IfDefragRequired = "True"Then

    2) option strict on disallows late binding    on lines      Console.WriteLine("Total Fragmented Files: {0}", OutParams("DefragAnalysis")("TotalFragmentedFiles"))

    This I can't work out how to fix?

    Any ideas please

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            Dim mContext As New ManagementNamedValueCollection()
            mContext.Add("__ProviderArchitecture", 64)
            mContext.Add("__RequiredArchitecture", True)
    
            Dim co As New ConnectionOptions
            co.Context = mContext
    
            Dim ms As New ManagementScope("root\CIMV2", co)
            ms.Connect()
    
            Dim oq As New ObjectQuery("Select * from Win32_Volume where DriveLetter = 'C:'")
            Dim oSearcher As New ManagementObjectSearcher(ms, oq)
    
            Dim oReturnCollection As ManagementObjectCollection = oSearcher.[Get]()
            For Each info As ManagementObject In oReturnCollection
                Dim OutParams As ManagementBaseObject = info.InvokeMethod("DefragAnalysis", Nothing, Nothing)
    
                Console.WriteLine("Defrag Recommended: {0}", OutParams("DefragRecommended"))
                Console.WriteLine("Total Fragmented Files: {0}", OutParams("DefragAnalysis")("TotalFragmentedFiles"))
                Console.WriteLine("Total Fragmented Files: {0}", OutParams("DefragAnalysis")("FragmentedFolders"))
                Console.WriteLine("ReturnValue: {0}", OutParams("ReturnValue"))
    
                If OutParams("DefragRecommended") = True Then
                    Console.WriteLine("You should defragment this volume.")
                Else
                    Console.WriteLine("You do not need to defragment this volume.")
                End If
    
            Next
    
        End Sub


    Darren Rose

    Monday, March 20, 2017 7:36 PM

Answers

  •  In order to execute the "DefragAnalysis" method,  you have to run the application with full administrator rights,  otherwise it will fail and the "ReturnValue" of the method will be 11 which is "Unknown Error".  The properties that you get from the class are returned as Object types so,  with Option Strict turned on you need to get the property object and cast them to the correct type.  For example, the "TotalFragmentedFiles" and "FragmentedFolders"  properties are both UInt64 type.   The "DefragRecommended" property is a Boolean type.

     You can look at the msdn documents on the Win32_XXXX classes and see what types the different properties are and what they indicate.  Look at the documents on the Win32_Volume class and the Win32_DefragAnalysis class.  The DefragAnaylisis class can be obtained by casting the "DefragAnalysis" property from the ManagementBaseObject returned by the Invoke method to another ManagementBaseObject .  Then you can access the properties of the DefragAnaylisis class from that.

     Sounds confusing but,  i'm sure once you see the code below, you will get the idea.  You can test this in a new form project with 1 Button and 1 RichTextBox added to the form.  As already said,  it must be ran as an administrator.  You can either right click on the VS launcher shortcut or your application's exe file and do the right click -> Run as administrator.  You can also modify your manifest file to require administrator rights.

    Imports System.Management
    
    Public Class Form1
        '#### Must Be Ran As An Administrator !!! ####
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            RichTextBox1.BackColor = Color.Black
            RichTextBox1.ForeColor = Color.Lime
            RichTextBox1.WordWrap = False
            RichTextBox1.Font = New Font("Courier New", 9.75F)
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim sb As New System.Text.StringBuilder
            Using mos As New ManagementObjectSearcher("Select * from Win32_Volume where DriveLetter = 'C:'")
                For Each info As ManagementObject In mos.Get
                    Dim OutParams As ManagementBaseObject = info.InvokeMethod("DefragAnalysis", Nothing, Nothing)
    
                    Dim retval As Integer = CInt(OutParams.GetPropertyValue("ReturnValue")) 'cast the ReturnValue of the DefragAnaysis to an Integer
                    If retval = Returncode.Success Then 'Make sure the ReturnValue = Success before going any further
    
                        Dim DefragRecommended As Boolean = CBool(OutParams.GetPropertyValue("DefragRecommended")) 'cast the DefragRecommended object to a Boolean
                        sb.AppendLine("Defrag Recommended:          " & DefragRecommended.ToString)
    
                        'cast the DefragAnalysis object to a ManagementBaseObject so you can get the property values from the Win32_DefragAnalysis class
                        Dim da As ManagementBaseObject = CType(OutParams.GetPropertyValue("DefragAnalysis"), ManagementBaseObject)
    
                        Dim TotalFragmentedFiles As UInt64 = CULng(da.GetPropertyValue("TotalFragmentedFiles")) 'cast the TotalFragmentedFiles to a UInt64
                        sb.AppendLine("Total Fragmented Files:      " & TotalFragmentedFiles.ToString)
    
                        Dim FragmentedFolders As UInt64 = CULng(da.GetPropertyValue("FragmentedFolders")) 'cast the FragmentedFolders to a UInt64
                        sb.AppendLine("Total Fragmented Folders:    " & FragmentedFolders.ToString)
    
                        Dim FilePercentFragmentation As UInt32 = CUInt(da.GetPropertyValue("FilePercentFragmentation"))
                        sb.AppendLine("File Percent Fragmentation:  " & FilePercentFragmentation.ToString & "%")
    
                    Else
                        sb.AppendLine("Return Value:             " & CType(retval, Returncode).ToString.Replace("_", " "))
                    End If
                Next
            End Using
    
            RichTextBox1.Text = sb.ToString
        End Sub
    
        Public Enum Returncode As Integer
            Success = 0
            Access_Denied = 1
            Not_Supported = 2
            Volume_Dirty_Bit_Is_Set = 3
            Not_Enough_Free_Space = 4
            Corrupt_Master_File_Table_Detected = 5
            Call_Canceled = 6
            Call_Cancellation_Request_Too_Late = 7
            Defrag_Engine_Is_Already_Running = 8
            Unable_To_Connect_To_Defrag_Engine = 9
            Defrag_Engine_Error = 10
            Unknown_Error = 11
        End Enum
    End Class
     

     Here is what you will get if you run it without administrator rights.

     

     And here is what you will get when ran as an administrator.

     

     The process may take some time to complete,  it takes about 30 to 40 seconds on my end to complete the analysis so,  you may want to run it in a separate thread so your app does not freeze up the whole time.   I guess it will depend on the size of the drive,  how many files and folders are on the drive,  and the speed of your system though.


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Monday, March 20, 2017 11:37 PM
    • Marked as answer by wingers Tuesday, March 21, 2017 12:39 PM
    Monday, March 20, 2017 11:34 PM

All replies

  • 2) option strict on disallows late binding    on lines      Console.WriteLine("Total Fragmented Files: {0}", OutParams("DefragAnalysis")("TotalFragmentedFiles"))

    You can't supply a second index to the object - it does not support a property of that form. 

    The object has already been created as a defrag analysis - there is no need to further qualify the reference as a defrag analysis.  However, you need to get access to the list of properties.  I cant see whether or not you can do that by property name. See:

    https://msdn.microsoft.com/en-us/library/system.management.managementbaseobject.item(v=vs.110).aspx

    The best option could be to iterate through the .Properties collection of outParams, comparing .Name to "TotalFragmentedFiles" and use the .Value property of the matching item.

    Monday, March 20, 2017 8:28 PM
  •  In order to execute the "DefragAnalysis" method,  you have to run the application with full administrator rights,  otherwise it will fail and the "ReturnValue" of the method will be 11 which is "Unknown Error".  The properties that you get from the class are returned as Object types so,  with Option Strict turned on you need to get the property object and cast them to the correct type.  For example, the "TotalFragmentedFiles" and "FragmentedFolders"  properties are both UInt64 type.   The "DefragRecommended" property is a Boolean type.

     You can look at the msdn documents on the Win32_XXXX classes and see what types the different properties are and what they indicate.  Look at the documents on the Win32_Volume class and the Win32_DefragAnalysis class.  The DefragAnaylisis class can be obtained by casting the "DefragAnalysis" property from the ManagementBaseObject returned by the Invoke method to another ManagementBaseObject .  Then you can access the properties of the DefragAnaylisis class from that.

     Sounds confusing but,  i'm sure once you see the code below, you will get the idea.  You can test this in a new form project with 1 Button and 1 RichTextBox added to the form.  As already said,  it must be ran as an administrator.  You can either right click on the VS launcher shortcut or your application's exe file and do the right click -> Run as administrator.  You can also modify your manifest file to require administrator rights.

    Imports System.Management
    
    Public Class Form1
        '#### Must Be Ran As An Administrator !!! ####
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            RichTextBox1.BackColor = Color.Black
            RichTextBox1.ForeColor = Color.Lime
            RichTextBox1.WordWrap = False
            RichTextBox1.Font = New Font("Courier New", 9.75F)
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim sb As New System.Text.StringBuilder
            Using mos As New ManagementObjectSearcher("Select * from Win32_Volume where DriveLetter = 'C:'")
                For Each info As ManagementObject In mos.Get
                    Dim OutParams As ManagementBaseObject = info.InvokeMethod("DefragAnalysis", Nothing, Nothing)
    
                    Dim retval As Integer = CInt(OutParams.GetPropertyValue("ReturnValue")) 'cast the ReturnValue of the DefragAnaysis to an Integer
                    If retval = Returncode.Success Then 'Make sure the ReturnValue = Success before going any further
    
                        Dim DefragRecommended As Boolean = CBool(OutParams.GetPropertyValue("DefragRecommended")) 'cast the DefragRecommended object to a Boolean
                        sb.AppendLine("Defrag Recommended:          " & DefragRecommended.ToString)
    
                        'cast the DefragAnalysis object to a ManagementBaseObject so you can get the property values from the Win32_DefragAnalysis class
                        Dim da As ManagementBaseObject = CType(OutParams.GetPropertyValue("DefragAnalysis"), ManagementBaseObject)
    
                        Dim TotalFragmentedFiles As UInt64 = CULng(da.GetPropertyValue("TotalFragmentedFiles")) 'cast the TotalFragmentedFiles to a UInt64
                        sb.AppendLine("Total Fragmented Files:      " & TotalFragmentedFiles.ToString)
    
                        Dim FragmentedFolders As UInt64 = CULng(da.GetPropertyValue("FragmentedFolders")) 'cast the FragmentedFolders to a UInt64
                        sb.AppendLine("Total Fragmented Folders:    " & FragmentedFolders.ToString)
    
                        Dim FilePercentFragmentation As UInt32 = CUInt(da.GetPropertyValue("FilePercentFragmentation"))
                        sb.AppendLine("File Percent Fragmentation:  " & FilePercentFragmentation.ToString & "%")
    
                    Else
                        sb.AppendLine("Return Value:             " & CType(retval, Returncode).ToString.Replace("_", " "))
                    End If
                Next
            End Using
    
            RichTextBox1.Text = sb.ToString
        End Sub
    
        Public Enum Returncode As Integer
            Success = 0
            Access_Denied = 1
            Not_Supported = 2
            Volume_Dirty_Bit_Is_Set = 3
            Not_Enough_Free_Space = 4
            Corrupt_Master_File_Table_Detected = 5
            Call_Canceled = 6
            Call_Cancellation_Request_Too_Late = 7
            Defrag_Engine_Is_Already_Running = 8
            Unable_To_Connect_To_Defrag_Engine = 9
            Defrag_Engine_Error = 10
            Unknown_Error = 11
        End Enum
    End Class
     

     Here is what you will get if you run it without administrator rights.

     

     And here is what you will get when ran as an administrator.

     

     The process may take some time to complete,  it takes about 30 to 40 seconds on my end to complete the analysis so,  you may want to run it in a separate thread so your app does not freeze up the whole time.   I guess it will depend on the size of the drive,  how many files and folders are on the drive,  and the speed of your system though.


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Monday, March 20, 2017 11:37 PM
    • Marked as answer by wingers Tuesday, March 21, 2017 12:39 PM
    Monday, March 20, 2017 11:34 PM
  • Hi IronRazerz

    Thank you so much for your response and full explanation on how to do it - it certainly makes a lot more sense to me now

    I had worked out how to get Defrag Recommended and that it needed running as administrator, but this really helped me understand the rest of it

    Thanks again :)


    Darren Rose

    Tuesday, March 21, 2017 12:39 AM
  • Just a note for anyone else reading this - you need to access 64-bit WMI values not 32-bit - so if like me you are using this in a 32-bit app running on a 64-bit machine then you do need to modify the code to set provider architecture as per my first post for it to work

    Dim mContext As New ManagementNamedValueCollection()
    mContext.Add("__ProviderArchitecture", 64)
    mContext.Add("__RequiredArchitecture", True)
    


    Darren Rose

    Tuesday, March 21, 2017 1:20 PM