Strange issue when compiling, then decompiling Select Case - c#

I'm seeing some strange behaviour when making a change to the following VB.net code. This is the original sourcecode:
Private Function ValidateSelectedId(ByVal purposeId As String) As Boolean
Dim possiblePurposes As New InfoCollector.Purpose
Dim isPurposeValid As Boolean = False
'Any of the following purposes (but only these)
'should be considered valid
Select Case UCase(purposeId)
Case UCase(possiblePurposes.FirstPurpose), _
UCase(possiblePurposes.SecondPurpose), _
UCase(possiblePurposes.ThirdPurpose), _
UCase(possiblePurposes.FourthPurpose)
isPurposeValid = True
Case Else
isPurposeValid = False
End Select
Return isPurposeValid
End Function
This is the new version. The only change is the addition of a fifth valid purpose:
Private Function ValidateSelectedId(ByVal purposeId As String) As Boolean
Dim possiblePurposes As New InfoCollector.Purpose
Dim isPurposeValid As Boolean = False
Select Case UCase(purposeId)
Case UCase(possiblePurposes.FirstPurpose), _
UCase(possiblePurposes.SecondPurpose), _
UCase(possiblePurposes.ThirdPurpose), _
UCase(possiblePurposes.FourthPurpose), _
UCase(possiblePurposes.FifthPurpose)
isPurposeValid = True
Case Else
isPurposeValid = False
End Select
Return isPurposeValid
End Function
I compiled this new version on my local PC and tested the functionality, and it worked fine. After checking this into our central code repository, and building it on the server however, the usage failed (it appeared to be ignoring the new purpose). While trying to figure out what is missing, I decompiled the .DLL found on the server, and this is what it gave me (Note: I've changed the variable names and reformatted slightly):
Private Function ValidateSelectedId(ByVal purposeId As String) As Boolean
Dim ValidateSelectedId As Boolean
Dim possiblePurposes As Purpose = New Purpose()
Dim isPurposeValid As Boolean = False
Dim str As String = Strings.UCase(purposeId)
If (Operators.CompareString(str, Strings.UCase(possiblePurposes.FirstPurpose), False) <> 0) Then
If (Operators.CompareString(str, Strings.UCase(possiblePurposes.SecondPurpose), False) <> 0
AndAlso (Operators.CompareString(str, Strings.UCase(possiblePurposes.ThirdPurpose), False) = 0
OrElse Operators.CompareString(str, Strings.UCase(possiblePurposes.FourthPurpose), False) <> 0)) Then
If (Operators.CompareString(str, Strings.UCase(possiblePurposes.FifthPurpose), False) = 0) Then
Return True
End If
isPurposeValid = False
End If
End If
Return isPurposeValid
End Function
I also tried decompiling this into C#, which might be a little easier to read for some of us:
private bool ValidateSelectedId(string purposeId)
{
bool ValidateSelectedId;
Purpose possiblePurposes = new Purpose();
bool isPurposeValid = false;
string str = Strings.UCase(purposeId);
if (Operators.CompareString(str, Strings.UCase(possiblePurposes.FirstPurpose), false) != 0)
{
if (Operators.CompareString(str, Strings.UCase(possiblePurposes.SecondPurpose), false) != 0
&& (Operators.CompareString(str, Strings.UCase(possiblePurposes.ThirdPurpose), false) == 0
|| Operators.CompareString(str, Strings.UCase(possiblePurposes.FourthPurpose), false) != 0))
{
if (Operators.CompareString(str, Strings.UCase(possiblePurposes.FifthPurpose), false) == 0)
{
return true;
}
isPurposeValid = false;
}
}
return isPurposeValid;
}
This however, seems to be doing something like the inverse of what I wanted, and not at all what the original source code is saying!
I can't see how the original source code could have been compiled to this. Could there be something wrong with my decompiler (I'm using Just Decompile from Telerik)? If so, how come the logic works on my local PC, but not on the server?
Could there actually be some kind of bug in the compile-process? Or am I being a complete Id**t, and simply misunderstanding the logic in the decompiled code?
Any relevant theories to explain this will be greatly appreciated.

Silly me.
I eventually discovered the reason this did not work on the server: There was another related bug which had been fixed locally, but not on the server.
Silly decompiler.
I was confused by the result from the decompiler, which was obviously messed up. I've used JustDecompile many times before, but never run across a problem like this. Apparently, it is unable to decompile the code from the above method in any reasonable fashion.
My assumptions are that some form of optimization is done during compilation, which JustDecompile has trouble understanding and displaying properly.
I just wanted to verify that my changes had been published to the server. Instead I was sent on a wild goose chase for a phantom bug. Lesson learned: Use the decompiler when needed, but do not automatically trust everything it tells you.

Related

Contract function with transaction

I have a question about programming VB.NET & Nethereum.
The contract address works flawlessly. For testing purposes I have built in a maintrace - pause function that can be set via function.
In the Remix tool + Metamask, the pause and resume function works perfectly.
I've been desperately looking for a solution for VB.NET (or else C #) for days:
The contract function (i have for test remove OnlyOwner variable in this Contract):
function SetPause() external returns (string memory) {
if (paused) {
paused = false;
emit Unpause();
Unpause;
return "Pause Set inactive";
} else {
paused = true;
Pause;
emit Pause();
return "Pause Set active";
}
}
When I address the function via VB.NET I get the return messages as normal, but my wallet does not carry out a transaction. Thus the status does not change. Other functions like transfer. Query of token names and balance work fine.
The VB.NET code:
Dim changeFunction As Task(Of String) = Contract.GetFunction("SetPause").SendTransactionAsync(senderAddress, gas)
changeFunction.Wait()
Textbox1.Text = changeFunction.Result
As I said, I get all the correct feedback, but no transactions are carried out (changes), only read queries. I also tried other VB.NET codes. Unsuccessful ...

Translating C# code to VB.net

I'm trying to translate this C# code to VB.net
var messages = animalmgr.ReadFile(thefilename);
//Getting method from manager
if (messages != null)
{
messages.ToList().ForEach(msg => Resultlst.Items.Add(msg));
}
I tried it like this:
Dim message = animalmgr.ReadFile(thefilename)
If (Not (message) Is Nothing) Then
'I don't know how the code below are supposed to be
message.ToList.ForEach(() => { }, Resultlst.Items.Add(msg))
End If
I would appreciate if anyone could help me out. Thanks.
VB lambda functions are a bit different. Here is how it looks in VB.Net:
message.ToList().ForEach(Sub(msg) Resultlst.Items.Add(msg))

Why does FireError fail in C# 2012, but works in VB, while FireInformation works in both?

I have an SSIS package in Visual Studio 2014, and I want to raise an error in a Script Component if any records traverse a particular path out of a 3rd party transformation. I WANT to do this in C# 2012, but the FireError method gives an error:
The best overloaded method match for 'Microsoft.SqlServer.Dts.Pipeline.Wrapper.IDTSComponentMetaData100.FireError(int, string, string, string, int, out bool)' has some invalid arguments
When I try to do this:
bool fireAgain = false;
IDTSComponentMetaData100 myMetaData;
myMetaData = this.ComponentMetaData;
myMetaData.FireError(0, "Script Component", "Invalid Records", string.Empty, 0, ref fireAgain);
but if I change FireError to FireInformation, it compiles and works -- except of course I need an error raised, not an informative event.
Also, if I use Visual Basic instead of C# as so:
Dim pbFireAgain As Boolean = False
Dim myMetaData As IDTSComponentMetaData100
myMetaData = Me.ComponentMetaData
myMetaData.FireError(0, "Script Component", "Invalid Records", String.Empty, 0, pbFireAgain)
Which is, I mean, literally the same exact thing but in a different language, it works fine. VB also works with FireInformation.
Obviously I can solve my immediate problem by using VB, but can someone tell me WHY this is this way? It seems like a specific issue with C#. As evidence, we have this on MSDN: https://msdn.microsoft.com/en-us/library/ms136031.aspx
Where the Script Component version of FireError is the only of eight examples to not have C# and VB versions (the logging one is poorly formatted, but they're both there).
I'm wondering if there's a debugger configuration that threatens to run C# code in an odd way, as this stackoverflow question answered, but the error I get is at design time -- Visual Studio springs the earlier "invalid arguments" error before I compile, so it knows something is off.
Thoughts?
You may be confusing the similar but different syntax for firing error vs information events from Script Components (data flow task) versus Script Tasks (control flow). The intellisense for Component indicates that the parameter is pbCancel whereas the fireAgain corresponds to the Information Task's parameter.
Script Component
C# Script Component example
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
bool cancel = false;
bool fireAgain = false;
this.ComponentMetaData.FireInformation(0, "My sub", "info", string.Empty, 0, ref fireAgain);
this.ComponentMetaData.FireError(0, "My sub", "error", string.Empty, 0, out cancel);
}
VB Component
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
Dim cancel As Boolean
Dim fireAgain As Boolean
Me.ComponentMetaData.FireInformation(0, "my sub", "info", String.Empty, 0, fireAgain)
Me.ComponentMetaData.FireError(0, "I hate vb", "Error", String.Empty, 0, cancel)
End Sub
There's no need to explicitly specify that a parameter is By Reference since that appears to be done in the definition versus the C# requirement to specify it also on invocation.
ByRef vs ByVal Clarification
Script Task
C#
public void Main()
{
bool fireAgain = false;
this.Dts.Events.FireInformation(0, "my sub", "info", string.Empty, 0, ref fireAgain);
// Note, no cancel available
this.Dts.Events.FireError(0, "my sub", "error", string.Empty, 0);
}
VB
Public Sub Main()
Dim fireAgain As Boolean = False
Me.Dts.Events.FireInformation(0, "my sub", "info desc", String.Empty, 0, fireAgain)
Me.Dts.Events.FireError(0, "my sub", "error desc", String.Empty, 0)
Dts.TaskResult = ScriptResults.Success
End Sub
Summary
C# requires you to specify ref and out keywords. They are not synonyms
VB lets you do whatever
Error event in Components have a cancel parameter
You are passing it by ref, not out, in your C#. I don't think VB.NET needs those keywords.

Conversion - 'Result' is not a member of 'System.Threading.Tasks.Task'

Using VS 2010, VB.NET, HTTPClient, .NET 4.0, and Windows Forms.
I am trying to get a windows application to consume JSON coming from a Web API that I have created. Web API works great and I can view the results from a browser. Found this article that I have been trying to get working only using VB.NET instead of C#.
http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-wpf-application
The critical part of the code is this function:
private void GetProducts(object sender, RoutedEventArgs e)
{
btnGetProducts.IsEnabled = false;
client.GetAsync("api/products/2").ContinueWith((t) =>
{
if (t.IsFaulted)
{
MessageBox.Show(t.Exception.Message);
btnGetProducts.IsEnabled = true;
}
else
{
var response = t.Result;
if (response.IsSuccessStatusCode)
{
response.Content.ReadAsAsync<IEnumerable<Product>>().
ContinueWith(t2 =>
{
if (t2.IsFaulted)
{
MessageBox.Show(t2.Exception.Message);
btnGetProducts.IsEnabled = true;
}
else
{
var products = t2.Result;
_products.CopyFrom(products);
btnGetProducts.IsEnabled = true;
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
I have tried to convert this to VB.NET but I am having issues with the t.Result saying "'Result' is not a member of 'System.Threading.Tasks.Task'."
Here is my attempt to convert it to VB.NET:
Private Sub GetProducts(sender As Object, e As RoutedEventArgs)
btnGetProducts.IsEnabled = False
client.GetAsync("api/products/2") _
.ContinueWith(Of HttpResponseMessage) _
(Function(t)
If t.IsFaulted Then
MessageBox.Show(t.Exception.Message)
btnGetProducts.IsEnabled = True
Else
'***************************************************************
Dim response = t.Result 'This is the line that is giving me grief. Error Msg: 'Result' is not a member of 'System.Threading.Tasks.Task'.
'***************************************************************
If response.IsSuccessStatusCode Then
response.Content.ReadAsAsync(Of IEnumerable(Of SendNotice)).ContinueWith _
(Function(t2)
If t2.IsFaulted Then
MessageBox.Show(t2.Exception.Message)
btnGetProducts.IsEnabled = True
Else
Dim products = t2.Result
_lstSN.CopyFrom(products)
btnGetProducts.IsEnabled = True
End If
End Function, TaskScheduler.FromCurrentSynchronizationContext())
End If
End If
End Function, TaskScheduler.FromCurrentSynchronizationContext())
End Sub
Any idea why I am getting this error and what am I missing in my code to allow me to catch the returning JSON data?
Thanks!
This is because VB.NET type inference is not great in Visual Studio 2010. You'll need to give the compiler a bit of extra help by specifying the actual type returned by your client.GetAsync(), like so:
client _
.GetAsync("api/products/2") _
.ContinueWith( _
Sub(t As Task(Of HttpResponseMessage))
...
End Sub, _
TaskScheduler.FromCurrentSynchronizationContext())
Note: I've changed your Function to Sub because I didn't see any Return statements.
Try this:
client.GetAsync("api/products/2") _
.ContinueWith(Sub(t)
If t.IsFaulted Then
.
.
.
Try changing your lambda from a Function to a Sub.

Use Microsoft Scripting Control to evaluate 'If' expressions (via c#)

I have some c# code that uses the Microsoft Scripting Control to evaluate some expressions:
using MSScriptControl; // references msscript.ocx
ScriptControlClass sc = new ScriptControlClass();
sc.Language = "VBScript";
sc.AllowUI = true;
try
{
Console.WriteLine(sc.Eval(txtEx.Text).ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
(txtEx is a simple text field)
Numerical expressions: "6+4", "cos(34)", "abs(-99)", "round(1.234, 2)" etc. are fine
Boolean expressions: "true or false", "1=2" are fine
But how can I evaluate a simple 'if'? I have tried "if(true, 2, 3)", "iif(true, 2, 3)", "if (true) then 2 else 3" and "if (true) then 2 else 3 endif"
Can anybody please help me to evaluate simple conditional expressions? Any help much appreciated!
RH
Try wrapping your IF-expression in a function
Function test
if (true) then
return true
else
return false
end if
End function
Add the function to the control and then use Run
Result = ScriptControl.Run("Test")
(the code above is not tested, but something along that way should work)
Check out this link for some more info
http://support.microsoft.com/kb/184740
using MSScriptControl; // references msscript.ocx
ScriptControlClass sc = new ScriptControlClass();
sc.Language = "VBScript";
sc.AllowUI = true;
// VBScript engine doesn’t have IIf function
// Adding wraper IIF function to script control.
// This IIF function will work just as VB6 IIf function.
sc.AddCode(#"Function IIF(Expression,TruePart,FalsePart)
If Expression Then
IIF=TruePart
Else
IIF=FalsePart
End IF
End Function");
try
{
//define x,y variable with value
sc.AddCode(#"x=5
y=6");
//test our IIF
Console.WriteLine(sc.Eval("IIF(x>y,x,y)").ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
You should consider using the expression evaluation engine that is part of Windows Workflow Foundation. Both the evaluator and the designer for it can be used separately from WF.
if (true) then return 2 else return 3
Thanks for the tips! After a bit more experimenting, based on Brummo's help, this seems to work:
txtEx contains this text:
function test
if (1=1) then
test = true
else
test = false
end if
end function
then
sc.AddCode(txtEx.Text);
and
object[] myParams = { };
Console.WriteLine(sc.Run("Test", ref myParams).ToString());
This isn't ideal, since I really wanted to evaluate an expression, without building, loading and evaluating a function. (I am surprised IIF doesn't work for simple one line if evaluation).

Categories