Enumerate an Enum

Started by stanl, August 22, 2019, 02:54:32 PM

Previous topic - Next topic

stanl


My understanding is the System.Net.HttpStausCode is more a lookup. The code below displays the numeric status. How would one create a ForEach or For Next loop to display all numeric status codes and description?

Code (WINBATCH) Select


ObjectClrOption( "useany", "System.Net.Http" )
oStatus = ObjectClrNew( 'System.Net.HttpStatusCode' )
v=oStatus.Forbidden
Message("Forbidden Status Code",v)
oStatus=0


Exit
[/code]

td

The MSFT documentation defines the inheritance for the enumeration as Object->ValueType->Enum->HttpStatusCode.  So it does not have a base class interface for enumeration.  In other words, it is a data type without methods or properties except those provided by the Object class.  It is just a bunch of values.

So to do what you want, you would need to go to MSFT's docs copy names, descriptions, and values into a file or some other storage structure and do whatever it is you want to with the information.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

Code (WINBATCH) Select


;Winbatch 2019B - Obtain Http Status Codes
;This should work with versions after 2013                 
;No error handling in this version
;Stan Littlefield, August 23,2019
;/////////////////////////////////////////////////////////////////////////////////////////////////////////


If Version( )< '2013A'
   Pause('Notice', 'Need 2013A or Newer Version of WinBatch')
   Exit
EndIf
cFile=Dirscript():"httpcodes.txt"
If FileExist(cFile) Then FileDelete(cFile)
cScript = '[Enum]::GetValues([System.Net.HttpStatusCode]) |':@CRLF
cScript = cScript:'ForEach-Object {':@CRLF
cScript = cScript:'[PSCustomObject]@{':@CRLF
cScript = cScript:'        Code = [int]$_ ':@CRLF
cScript = cScript:'        Description = $_.toString()':@CRLF
cScript = cScript:'    }':@CRLF
cScript = cScript:'  } | out-file "%cFile%"'
BoxOpen("Please Wait","Processing... ")
ObjectClrOption("useany", "System.Management.Automation")
objAutoPs = ObjectClrNew("System.Management.Automation.PowerShell")
oPshell = objAutoPs.Create()
oScope = ObjectType("BOOL",@TRUE)
oPshell.AddScript(cScript,oScope)
objAsync = oPshell.BeginInvoke()
oPShell.EndInvoke(objAsync)     
oPshell.Dispose()
oPshell=0
BoxShut()
If FileExist(cFile)
   runwait("Notepad",cFile)
Else
   Display(2,"File Not Created",cFile)
Endif
Exit

stanl

This is a little more generic. My original request to obtain status codes was due to an error I was getting trying to connect to a WEB IDE server and wanted to see if it was interpreted with a description rather than just a number. Then I got to thinking about enums in general and how they might be like WB's maps. Finally wondered if WB could write a C# dll to create or update custom enums for scripts (or would it just be better to stick with maps : albeit the dll might work with versions after 2013).


Anyway. The Powershell code seems to handle all sorts of enums.
Code (WINBATCH) Select


;Winbatch 2019B - Use CLR/Powershell to detail enumerations
;This should work with versions after 2013                 
;Stan Littlefield, August 25,2019
;/////////////////////////////////////////////////////////////////////////////////////////////////////////
Gosub udfs
IntControl(73,1,0,0,0)
If Version( )< '2013A'
   Pause('Notice', 'Need 2013A or Newer Version of WinBatch')
   Exit
EndIf
enums="System.Net.HttpStatusCode":@TAB
enums=enums:"System.ConsoleColor":@TAB
enums=enums:"System.DateTimeKind":@TAB
enums=enums:"System.DayOfWeek":@TAB
enums=enums:"System.ConsoleKey":@TAB
enums=enums:"System.StringComparison":@TAB


enum = AskItemlist("Select Enumeration", enums, @TAB, @SORTED, @SINGLE, @FALSE)




cFile=Dirscript():"%enum%.txt"
If FileExist(cFile) Then FileDelete(cFile)
enumvalues()
If FileExist(cFile)
   runwait("Notepad",cFile)
Else
   Display(2,"File Not Created",cFile)
Endif
Exit


:WBERRORHANDLER
geterror()
Message("Error Encountered",errmsg)
Exit


:udfs
#DefineSubroutine enumvalues()
IntControl(73,1,0,0,0)
cScript = '[Enum]::GetValues([%enum%]) |':@CRLF
cScript = cScript:'ForEach-Object {':@CRLF
cScript = cScript:'[PSCustomObject]@{':@CRLF
cScript = cScript:'        Code = [int]$_ ':@CRLF
cScript = cScript:'        Description = $_.toString()':@CRLF
cScript = cScript:'    }':@CRLF
cScript = cScript:'  } | out-file "%cFile%"'
BoxOpen("Please Wait","Processing... ")
ObjectClrOption("useany", "System.Management.Automation")
objAutoPs = ObjectClrNew("System.Management.Automation.PowerShell")
oPshell = objAutoPs.Create()
oScope = ObjectType("BOOL",@TRUE)
oPshell.AddScript(cScript,oScope)
objAsync = oPshell.BeginInvoke()
oPShell.EndInvoke(objAsync)     
oPshell.Dispose()
oPshell=0
BoxShut()
Return (1)
:WBERRORHANDLER
oPshell=0
geterror()
Message("Error Encountered",errmsg)
Exit
#EndSubroutine


#DefineSubRoutine geterror()
   wberroradditionalinfo = wberrorarray[6]
   lasterr = wberrorarray[0]
   handlerline = wberrorarray[1]
   textstring = wberrorarray[5]
   linenumber = wberrorarray[8]
   errmsg = "Error: ":lasterr:@LF:textstring:@LF:"Line (":linenumber:")":@LF:wberroradditionalinfo
   Return(errmsg)
#EndSubRoutine


Return



td

The HttpStatusCode class does appear to inherit from the System.Enum class which supports a form of iteration.

However, System.Enum is an abstract class that WIL CLR hosting can't get access to.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

I need to correct a couple of misleading statements I made in my previous two posts on this topic. 

In the original response, I mentioned that only the object classes methods and properties are available for a given enumeration.  While that is mostly true for WinBatch CLR hosting it is not true for all .Net framework hosting environments.  The reason for this is not because enum is an abstract class which was the second erroneous statement I made.     

Without taking a deep dive into the technical explanation, the unavailability of the System.Enum class methods and properties has to do with the way WinBatch needs to host the CLR.  MSFT decided to be "helpful" when implementing the hosting interfaces used by WinBatch.  Basically, MSFT's interfaces dumb-down value data structures like System.Enum to System.Int32 when they are given to WinBatch CLR hosting. 

Here is a simple script that illustrates the point:
Code (winbatch) Select
ObjectClrOption("useany", "System.Net") 
enumHttpStatus = ObjectClrNew('System.Net.HttpStatusCode')
EnumType = enumHttpStatus.GetType()
Message("What the $!&%*?",  Enumtype.ToString())
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

should be "What the $!&%%*?"
[/size]
But technically WB's CLR does work, just uses PS as a helper.... much like leveraging VBA, OLEDB and others. The problem would be in passing PS variables or objects back to WB. 

Thanks for looking and all your insights.

td

Of course, you can always keep an assembly written in C# around with a set of helper methods in a single class.  The approach does make moving data back and forth relatively simple. 

You can always use the integer values with an enumeration in WIL scripts without any outside help.  In most cases, it is simply a matter of passing an integer to a method or testing a returned value against an integer.  With the caveat that you may need to use ObjectClrType to cast the integer to the appropriate enum type when passing to a method.  This is necessary only when you are passing an enum value to a method that is overloaded and the CLR can't work out the method signature without a little assistance from WIL.   
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade