I'm trying to use an arraylist as the parameter to String.Format.
msg = msg & String.Format("<td>{0}</td>" & _
"<td>{1}</td>" & _
"<td>{2}</td>" & _
"<td>{3}</td>" & _
"<td>{4}</td>" & _
"<td>{5}</td>" & _
"<td>{6}</td>" & _
"<td>{7}</td>" & _
"<td>{8}</td>", param)
where param is an ArrayList and the contents are thus (copied from watch list):
+ (0) 9 {Integer} Object
+ (1) 3 {Integer} Object
+ (2) 5 {Integer} Object
+ (3) "180" {String} Object
+ (4) 0D {Decimal} Object
+ (5) 6.788D {Decimal} Object
+ (6) #3/13/2009# {Date} Object
+ (7) "2004" {String} Object
+ (8) "" {String} Object
But this code throws a FormatException
Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
Am I wrong that it's possible to use an arraylist? If it is possible, any clues as to why it would be throwing such an error?
Thanks
Does it accept an ArrayList?
Did you try:
"<td>{8}</td>", param.ToArray())
You probably need to pass in an object array and not an ArrayList. If you change the code as such you may see what is going wrong:
msg = msg & String.Format("<td>{0}</td>", param)
It should print something like
< td>System.ArrayList< td>
Have you tried this ?
msg = msg & String.Format("<td>{0}</td>" & _
"<td>{1}</td>" & _
"<td>{2}</td>" & _
"<td>{3}</td>" & _
"<td>{4}</td>" & _
"<td>{5}</td>" & _
"<td>{6}</td>" & _
"<td>{7}</td>" & _
"<td>{8}</td>", param.ToArray())
Related
I have a VB.net program that I am trying to add a bitlocker lookup tool that will search active directory for the machine name, and display the "Password ID" as well as the "Recovery Password"
So far my script/code works flawlessly for the lookup and displaying the Recovery Password, but I cannot get it to display the Password ID.
I've tried:
Item.Properties("msFVE-RecoveryGuid")(0)
Which returns the error "System.InvalidCastException: Conversion from type 'Byte()' to type 'String' is not valid."
Item.Properties("msFVE-RecoveryGuid")(0).ToString
Which returns "System.Byte[]"
Item.Properties("msFVE-RecoveryGuid").ToString
Which returns "System.DirectoryServices.ResultPropertyValueCollection"
So far in my searching I've only seen C# examples, and I haven't been able to translate.
The same for Recovery Password works however:
(Item.Properties("msFVE-RecoveryPassword")(0))
Here is the larger snippet of what I have for context:
Dim RootDSE As New DirectoryEntry("LDAP://RootDSE")
Dim DomainDN As String = RootDSE.Properties("DefaultNamingContext").Value
Dim ADsearch As New DirectorySearcher("LDAP://" & DomainDN)
ADsearch.Filter = ("(&(objectClass=computer)(name=" & MachineName & "))")
Dim ADresult As SearchResult = ADsearch.FindOne
Dim ADpath As String = ADresult.Path
Dim BTsearch As New DirectorySearcher()
BTsearch.SearchRoot = New DirectoryEntry(ADpath)
BTsearch.Filter = "(&(objectClass=msFVE-RecoveryInformation))"
Dim BitLockers As SearchResultCollection = BTsearch.FindAll()
Dim Item As SearchResult
Dim longTempstring As String = ""
For Each Item In BitLockers
If Item.Properties.Contains("msFVE-RecoveryGuid") Then
Dim tempstring As String = Item.Properties("msFVE-RecoveryGuid")(0).ToString
longTempstring = longTempstring & tempstring & vbNewLine
'ListBox2.Items.Add(Item.Properties("msFVE-RecoveryGuid")(0))
End If
If Item.Properties.Contains("msFVE-RecoveryPassword") Then
ListBox1.Items.Add(Item.Properties("msFVE-RecoveryPassword")(0))
End If
Next
MsgBox(longTempstring)
So I figured out that I needed to convert the bytes to hex in order to get them to match what is viewed in the Microsoft Management Console. Once I began doing that the only problem I ran into is that I discovered the indexing of the byte arrays are not in the same order as they are in Active Directory. -- so instead of looping I had to list out each index of the Byte array and sort them to their proper positions so that they match how they show up in AD.
My end function is:
Function bitread(ByVal GUID As Byte())
Dim tempVar As String
tempVar = GUID(3).ToString("X02") & GUID(2).ToString("X02") _
& GUID(1).ToString("X02") & GUID(0).ToString("X02") & "-" _
& GUID(5).ToString("X02") & GUID(4).ToString("X02") & "-" _
& GUID(7).ToString("X02") & GUID(6).ToString("X02") & "-" _
& GUID(8).ToString("X02") & GUID(9).ToString("X02") & "-" _
& GUID(10).ToString("X02") & GUID(11).ToString("X02") _
& GUID(12).ToString("X02") & GUID(13).ToString("X02") _
& GUID(14).ToString("X02") & GUID(15).ToString("X02")
Return tempVar
End Function
Called with:
bitread(Item.Properties("msFVE-RecoveryGUID")(0))
we are generating a mass of documents very dynamically. Therefore we concatenate source code and build a dll at runtime. This is running since windows XP.
Now we are in tests of windows 10 and it fails compiling this dll with the error "BC31019: Unable to write to output file 'C:\Users[name]AppData\Local\Temp\xyz.dll': The specified image file did not contain a resource section"
For testing purposes we remove all generated source code and replace it by a rudimental class with only one function (throwing an exception with specified text) and no referenced assemblies.
This is also running on all machines except windows 10. Same error.
Can anybody guess why?
This is the rudimental method
Public Sub Compile()
Dim lSourceCode = "Namespace DynamicOutput" & vbCrLf &
" Public Class Template" & vbCrLf &
" Sub New()" & vbCrLf &
" End Sub" & vbCrLf &
" Public Sub Generate(ByVal spoolJob As Object, ByVal print As Object)" & vbCrLf &
" Throw New System.Exception(""Generate reached"")" & vbCrLf &
" End Sub" & vbCrLf &
"" & vbCrLf &
" End Class" & vbCrLf &
"End Namespace"
Dim lParams As CodeDom.Compiler.CompilerParameters = New CodeDom.Compiler.CompilerParameters
lParams.CompilerOptions = "/target:library /rootnamespace:CompanyName /d:TRACE=TRUE /optimize "
lParams.IncludeDebugInformation = True
lParams.GenerateExecutable = False
lParams.TreatWarningsAsErrors = False
lParams.GenerateInMemory = True
Dim lProviderOptions As New Dictionary(Of String, String) From {{"CompilerVersion", "v4.0"}}
Dim lResult As CodeDom.Compiler.CompilerResults = Nothing
Using provider As New VBCodeProvider(lProviderOptions)
lResult = provider.CompileAssemblyFromSource(lParams, lSourceCode)
End Using
' ... check for errors
Dim lInstance As Object = lResult.CompiledAssembly.CreateInstance("CompanyName.DynamicOutput.Template")
lInstance.GetType.GetMethod("Generate").Invoke(lInstance, New Object() {Me.SpoolJob, Me.Print})
End Sub
There's a web service set up that our application is calling.
When calling this function through a browser (Tested using Mozilla Firefox), this function writes to the log file correctly (with the values that we provide to it). However, when calling this function through a tablet (tested on the same network and on a different network), nothing is written to the logs.
It's simple, looks like this:
<WebMethod()> _
Public Function CreateClient( _
ByVal strUserID As String, _
ByVal strVehicleID As String, _
ByVal strUnit As String, _
ByVal strHouse As String, _
ByVal strStreet As String, _
ByVal strCity As String, _
ByVal strContactName As String, _
ByVal strPhone As String, _
ByVal strComments As String)
Dim strReturn As String = "14"
Dim strLog As String = ""
strLog = "CreateClient strUserID = " & strUserID & ", strVehicleID = " & strVehicleID & ", strUnit = " & strUnit & ", strHouse = " & strHouse & ", strStreet = " & strStreet & ", strCity = " & strCity
strLog &= ", strContactName=" & strContactName & ", strPhone=" & strPhone & ", strComments=" & strComments
Class1.WriteLogEntry(strLog, Class1.LOG_TYPE_DEBUG)
Return strReturn
End Function
We know we're reaching and calling the correct web service & function because when we change the return value, the tablet shows the correct value after each deployment. Eg: when the return value is set to "1", the tablet gets back a "1", and after changing it to a "14", the tablet also gets back a "14".
Does anyone know why the logs are not being written, and/or how to fix this?
Note: If you need to see the android code for how we're calling it, I'll post it, but again, I don't think it's necessary since we already know that we're calling it properly and getting the correct return value.
Not sure what the problem was, but after changing 2 things, the logs started working again:
Moved all the code from Class1 to a Module (Module)
Changed the target file it was saving to.
Could it be possible that there was something else locking onto the file, thus preventing this log from being written? Or perhaps Classes and Modules don't have the same file writing permissions?
I have a Collection of servers which I take from a multiline textbox.
I have some simple validation which should be trimming whitespace (to prevent an entry being created for blank line), but it's not working.
For example, if Me.formServers.txtServers.Text is as follows, the lengths of the lines are returned as 5, 5, 5 and 4. How can I correctly calculate the length of each line and thus avoid erroneous items being added to my Collection? Thanks.
TTSA
TTSB
TTSC
TTSD
Here is my code
Me.Servers = New Collection ' Reset 'Servers' to ensure only the correct servers are included
For Each Server As String In Me.formServers.txtServers.Text.Split(vbLf)
If Not Server.Trim.Length = 0 Then Me.Servers.Add(Server)
MsgBox(Server.Length)
Next
This test was interesting:
Dim s As String = "TTSA" & vbCrLf
s &= "TTSB" & vbLf
s &= "TTSC" & vbCr
s &= "TTSD" & Environment.NewLine
s &= "TTSE" & vbNewLine
Dim Excluded() As String
Excluded = s.Split({vbCrLf, vbLf}, StringSplitOptions.None)
For Each s In Excluded
Debug.Print(s & " " & s.Length)
Next
result:
TTSA 4
TTSB 4
TTSC ' vbCr was not in list so is still in the string
TTSD 9
TTSE 4
0 ' last separator honored
Corrected to:
Excluded = s.Split({vbCrLf, vbLf, vbCr}, _
StringSplitOptions.RemoveEmptyEntries)
A WQL query in WMI using the COM API returns a SWbemObjectSet. From this, we can use the ItemIndex method to iterate over all objects in the set, resulting in many SWbemObjects. These have a Properties_ property, which returns a SWbemPropertySet.
This object has a Count property, but no ItemIndex method, instead only an Item method, which takes a string name of the property to fetch. I'd like to iterate over all available properties, thus I don't have the name available. I've tried calling an ItemIndex method, but (as per the documentation) it does not exist on this object. There are many VBScript documents around that do something like For Each prop in object.Properties_, so I assume this is somehow possible.
How can I find all properties?
First, the ItemIndex property only exist in some versions of the Microsoft WMI Scripting Library you can find more info about this topic on this article which I wrote some time ago
Be careful when you import the Microsoft WMI Scripting Library (The code uses Delphi but the same applies to any language using this Library).
Now to iterate over the elements of an SWbemPropertySet you must get a instance to the enumerator accessing the _NewEnum property which provides a method for enumerating a collection of variants using the IEnumVARIANT interface. This is done automagically by vbscript, but in others languages like Delphi or C++ must be done manually.
Try this Delphi sample
{$APPTYPE CONSOLE}
uses
SysUtils,
ActiveX,
ComObj,
Variants,
WbemScripting_TLB in 'WbemScripting_TLB.pas';
procedure ShowProperties(const WMINameSpace, WMIClass : string);
var
WMIServices : ISWbemServices;
SWbemObjectSet : ISWbemObjectSet;
SObject : ISWbemObject;
LProperty : ISWbemProperty;
Enum, Enum2 : IEnumVariant;
TempObj, TempObj2: OleVariant;
Value : Cardinal;
SWbemPropertySet: ISWbemPropertySet;
begin
WMIServices := CoSWbemLocator.Create.ConnectServer('.', WMINameSpace,'', '', '', '', 0, nil);
SWbemObjectSet := WMIServices.ExecQuery(Format('Select * FROM %s',[WMIClass]), 'WQL', 0, nil);
Enum := (SWbemObjectSet._NewEnum) as IEnumVariant;
if (Enum.Next(1, TempObj, Value) = S_OK) then
begin
SObject := IUnknown(TempObj) as ISWBemObject;
SWbemPropertySet := SObject.Properties_;
Enum2 := (SWbemPropertySet._NewEnum) as IEnumVariant;
while (Enum2.Next(1, TempObj2, Value) = S_OK) do
begin
LProperty := IUnknown(TempObj2) as ISWbemProperty;
Writeln(LProperty.Name);
TempObj2:=Unassigned;
end;
TempObj:=Unassigned;
end;
end;
begin
try
CoInitialize(nil);
try
ShowProperties('root\cimv2','Win32_BaseBoard');
finally
CoUninitialize;
end;
except
on E:EOleException do
Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
on E:Exception do
Writeln(E.Classname, ':', E.Message);
end;
Writeln('Press Enter to exit');
Readln;
end.
I hope which you can translate this sample to the Go language.
You need to query the object class to get all the properties. Here's an example where the object class properties are used to convert a WMI query to a stringified JSON object.
function getWMIObjectJSON(strNameSpace,strClass,strFilter)
strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
strComputer & "\" & strNameSpace)
Set objClass = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
strComputer & "\" & strNameSpace & ":" & strClass)
colCount=0
rtn="{""description"":""" & escStr(strNameSpace & ":" & strClass & " " & strFilter) & """,""title"":""" & _
escStr(strNameSpace & ":" & strClass) & """,""columns"":["
For Each objClassProperty In objClass.Properties_
if colCount>0 then rtn=rtn & ","
rtn=rtn & """" & escStr(objClassProperty.Name) & """"
colCount=colCount + 1
Next
Set colData = objWMIService.ExecQuery("Select * from " & strClass & " " & strFilter)
rtn=rtn & "],""record_count"":" & colData.Count & ",""records"":["
rowCount=0
For Each objData In colData
if rowCount > 0 then rtn=rtn & ","
rtn=rtn & "{"
colCount=0
For Each objClassProperty In objClass.Properties_
if colCount > 0 then rtn=rtn & ","
rtn=rtn & """" & escStr(objClassProperty.Name) & """:""" & _
escStr(objData.Properties_(objClassProperty.Name).Value) & """"
colCount=colCount + 1
Next
rtn=rtn & "}"
rowCount=rowCount + 1
Next
rtn=rtn & "]}"
getWMIObjectJSON = rtn
end function
desktop = getWMIObjectJSON("root\cimv2","Win32_Desktop","where Name like '%u%'")
WScript.Echo desktop
<package>
<job id="wmiExample">
<script language="VBScript" src="wmi.vbs"/>
<script language="JScript">
var desktop = eval("(" + getWMIObjectJSON("root\cimv2","Win32_Desktop","") + ")");
for(d in desktop.records){
WScript.Echo(desktop.records[d].Name);
}
</script>
</job>
</package>