E1740 lambda captured variable of type "..." cannot be copied to closure class field of type "..." - visual-studio

I have recently installed VS 2019 and opened up my project I created in VS 2017. The software works fine but there is a bug in VS with lambda captured variables. MS apparently is aware of said issue, but I was wondering if anyone else had come across this recently and if you have, have you managed to solve it?
Example bit of code from my project, the intellisense has flagged up every line where "[this]" appears. The error / bug reads
lambda captured variable of type "MainPage^*" cannot be copied to closure class field of type "MainPage^"
if (_serialPort1 != nullptr)
{
concurrency::create_task(WriteToSerialDeviceAsync(cancellationTokenSource_serialPort1->get_token(),
Arduino_Device.Outgoing_Bytes, PORT_1)).then([this](concurrency::task<void> previousTask) {
try
{
previousTask.get();
}
catch (Platform::COMException^ ex)
{
this->DataStreamWindow->Text += "\r\n!EXCEPTION CAUGHT! " + ex->Message;
}
});
}

Ok, I managed to stumble upon a somewhat ugly hack to fix this.
Rather than pass [this] into the lambda, I added the line auto _this = this; prior to creating any tasks. This did however mean that any variables which were accessed using this->SomeVariable became _this->SomeVariable.
So my example above now looks like this.
if (_serialPort1 != nullptr)
{
auto _this = this;
concurrency::create_task(WriteToSerialDeviceAsync(cancellationTokenSource_serialPort1->get_token(),
Arduino_Device.Outgoing_Bytes, PORT_1)).then([_this](concurrency::task<void> previousTask) {
try
{
previousTask.get();
}
catch (Platform::COMException^ ex)
{
_this->DataStreamWindow->Text += "\r\n!EXCEPTION CAUGHT! " + ex->Message;
}
});
}
Hope this is of use.

If so then why copying outside the task? You could do
if (_serialPort1 != nullptr)
{ concurrency::create_task(WriteToSerialDeviceAsync(cancellationTokenSource_serialPort1->get_token(),
Arduino_Device.Outgoing_Bytes, PORT_1)).then([_this = this](concurrency::task<void> previousTask) {
try
{
previousTask.get();
}
catch (Platform::COMException^ ex)
{
_this->DataStreamWindow->Text += "\r\n!EXCEPTION CAUGHT! " + ex->Message;
}
});
}
But based on your problem this is not the proper solution. You better find what's wrong with your project migration to VS 2019.

Related

Implementing Jump Hosts with SSHJ

Somebody asked for this and there is a pull-request which contains code that somehow was rewritten before it got merged and somebody managed to code a solution based on the pull-request. However, there is no example for the final version in that library.
Therefore, that doesn't really help me with my limited understanding of ssh and all. Basically there are two scenarios I want to solve:
common SSH-session via some jump-hosts:
user1#jump1.com
user2#jump2.com
user3#jump3.com
admin#server.com
ending in an ssh-session where the connecting user is free to work around in that ssh-shell at server.com, i.e. what a normal ssh admin#server.com-command would do in the shell on jump3.com.
like the above but ending in a port forwarding to server.com:80
That is possible with ssh's ProxyCommand, but I want to code this with SSHJ. And that's where I fail to figure out how to do this.
What I have now is
SSHClient hop1 = new SSHClient();
try {
Path knownHosts = rootConfig.getKnownHosts();
if (knownHosts != null) {
hop1.loadKnownHosts(knownHosts.toFile());
} else {
hop1.loadKnownHosts();
}
Path authenticationFile = hop1Config.getAuthenticationFile();
if (authenticationFile != null) {
KeyProvider keyProvider = hop1.loadKeys(authenticationFile.toString(), (String) null);
hop1.authPublickey(hop1Config.getUser(), keyProvider);
} else {
hop1.authPassword(hop1Config.getUser(), hop1Config.getPassword());
}
// I found these methods:
hop1.getConnection();
hop1.getSocket();
// and now what?
} catch (IOException e) {
logger.error("Failed to open ssh-connection to {}", hop1Config, e);
}
I noticed class LocalPortForwarder.DirectTCPIPChannel, but I don't know with what values I should instantiate it or how to use it with the rest afterwards.

Requesting Android permissions in a class (Xamarin)

I'm trying to request a permission at runtime for my app. I use a service provider to talk between the portable class and Android.
I start by calling this code on button press in the PCL:
using (new Busy(this))
{
var locationHelper = scope.Resolve<ILocationHelper>();
locationHelper.GetLocation(this);
}
This calls my Android level service:
public class AndroidLocationHelper : ILocationHelper, ILocationListener
{
readonly string[] PermissionsLocation =
{
Manifest.Permission.AccessCoarseLocation
};
const int RequestLocationId = 0;
public void GetLocation(SearchViewModel viewModel)
{
try
{
const string permission = Manifest.Permission.AccessCoarseLocation;
if (((int)Build.VERSION.SdkInt < 23) || (CheckSelfPermission(permission) == Permission.Granted))
{
}
else
RequestPermissions(PermissionsLocation, RequestLocationId);
}
catch (Exception ex)
{
Debug.WriteLine("Error while getting Location service");
Debug.WriteLine(ex.Message);
Messaging.AlertUser("There was an error with determining your location");
}
}
However, I get two errors on CheckSelfPermission and RequestPermissions. These two methods are only available to activities. The code works fine in MainActivity; however, I want to ask for permissions when the user hits a button, not in OnCreate or OnResume, etc.
Thanks for any help.
In your Android project, You can use this and use the Dependency Service to call it in Xamarin.Forms PCL project later:
var thisActivity = Forms.Context as Activity;
ActivityCompat.RequestPermissions(thisActivity, new string[] {
Manifest.Permission.AccessFineLocation }, 1);
ActivityCompat.RequestPermissions(thisActivity,
new String[] { Manifest.Permission.AccessFineLocation },
1);
You can try with ContextCompat.CheckSelfPermission, passing the application context, like this:
ContextCompat.CheckSelfPermission(Android.App.Application.Context, permission)
Update
In case of ActivityCompat.RequestPermissions, which requires an activity reference, you can keep track of the current activity. There is a very handy lib for that, called "CurrentActivityPlugin". You can find at https://github.com/jamesmontemagno/CurrentActivityPlugin
Rafael came up with a solution but I found another option that is a lot less effort just using MessagingCenter. In the MainActivity's OnCreate add a receiver that runs all the location code, that way you have access to all of the activities methods (and there are a bunch of tutorials on doing location services in MainActivity). Then add the Send inside of your service (the class).
To expound Rafael Steil's answer, I tried the suggested CurrentActivityPlugin and it worked on me. In my case I am trying to execute a voice call which needs CALL_PHONE permission. Here is the code snippet in your case: I used the ContextCompat & ActivityCompat so that I don't need to check the VERSION.SdkInt
using Plugin.CurrentActivity;
public void GetLocation(SearchViewModel viewModel){
var context = CrossCurrentActivity.Current.AppContext;
var activity = CrossCurrentActivity.Current.Activity;
int YOUR_ASSIGNED_REQUEST_CODE = 9;
if (ContextCompat.CheckSelfPermission(context, Manifest.Permission.AccessCoarseLocation) == (int)Android.Content.PM.Permission.Granted)
{
//Permission is granted, execute stuff
}
else
{
ActivityCompat.RequestPermissions(activity, new string[] { Manifest.Permission.AccessCoarseLocation }, YOUR_ASSIGNED_REQUEST_CODE);
}
}
It's dead simple
public bool CheckPermission()
{
const string permission = Manifest.Permission.ReceiveSms;
return ContextCompat.CheckSelfPermission(Forms.Context, permission) == (int) Permission.Granted;
}

JavaFx controlsFX AutoCompletionEvent doesn't work

I want to handle the AutoCompletionEvent of the controlsFX 8.0.5 framework, but somehow it will be never fired?! When no suggestions are available there should be one entry with "new..." and when this entry is chosen I want to do something. Therefore I set an EventHandler.
I implemented the binding like this:
AutoCompletionBinding<String> bind = TextFields.bindAutoCompletion(tf, sr -> {
List<String> shownSuggestions = new ArrayList<String>();
for (Client c : suggestions) {
if (!sr.getUserText().isEmpty()
&& c.toString().toLowerCase().startsWith(sr.getUserText().toLowerCase())) {
shownSuggestions.add(c.toString());
}
if (shownSuggestions.isEmpty()) {
if (sr.getUserText().isEmpty()) {
shownSuggestions.add(NEW_PARTY);
} else {
shownSuggestions.add(sr.getUserText() + NEW_PARTY_WITH_NAME);
}
}
}
return shownSuggestions;
});
And this is my EventHandler:
bind.setOnAutoCompleted(new EventHandler<AutoCompletionEvent<String>>() {
#Override
public void handle(AutoCompletionEvent<String> event) {
if (event.getCompletion().equals(NEW_PARTY)) {
System.out.println("new party chosen");
} else if (event.getCompletion().endsWith(NEW_PARTY_WITH_NAME)) {
System.out.println("new party with input chosen");
}
event.consume();
}
});
But there is no output on the console.
Can someone please help me? I'm trying this for days now...
regards
There is a bug in controlsFX 8.0.5 causing that the event never gets fired. So the code is correct, but it's never called.
Bug report in controlsFX 8.0.5

dslVersion - How to increment but still support older versions?

Tech: Visual Studio 2010, Visual Studio Visualization & Modeling SDK
We have a commercial Visual Studio 2010 DSL, when we release a new version we want to increment the version number. I open the DslDefinition.dsl and update the version number as required and then do a Transform all templates so that the changes get reflected. The DslPackage 'source.extension.vsixmanifest' gets updated fine and shows the new version number.
The issue is however is that when someone opens a model created from version 1.0.0.0 with the updated version 1.0.0.1 then they can't open the model, the reason seems to be that the 'dslVersion' in the *.diagram file is set to 1.0.0.0 which has been outdated, I can fix by manually updating the dslVersion but there seems to be no way to set a supported version range.
Is there any fix for this?
I have solved this issue by overriding the 'CheckVersion' method which sits in the '*SerializationHelper' class. My implementation is below.
partial class ProductSerializationHelper
{
protected override void CheckVersion(Microsoft.VisualStudio.Modeling.SerializationContext serializationContext, System.Xml.XmlReader reader)
{
#region Check Parameters
global::System.Diagnostics.Debug.Assert(serializationContext != null);
if (serializationContext == null)
throw new global::System.ArgumentNullException("serializationContext");
global::System.Diagnostics.Debug.Assert(reader != null);
if (reader == null)
throw new global::System.ArgumentNullException("reader");
#endregion
global::System.Version expectedVersion = new global::System.Version("2.5.0.0");
string dslVersionStr = reader.GetAttribute("dslVersion");
if (dslVersionStr != null)
{
try
{
global::System.Version actualVersion = new global::System.Version(dslVersionStr);
// #### THIS IS WHERE I CHANGED FROM '!=' to '>'
if (actualVersion > expectedVersion)
{
ProductSerializationBehaviorSerializationMessages.VersionMismatch(serializationContext, reader, expectedVersion, actualVersion);
}
}
catch (global::System.ArgumentException)
{
ProductSerializationBehaviorSerializationMessages.InvalidPropertyValue(serializationContext, reader, "dslVersion", typeof(global::System.Version), dslVersionStr);
}
catch (global::System.FormatException)
{
ProductSerializationBehaviorSerializationMessages.InvalidPropertyValue(serializationContext, reader, "dslVersion", typeof(global::System.Version), dslVersionStr);
}
catch (global::System.OverflowException)
{
ProductSerializationBehaviorSerializationMessages.InvalidPropertyValue(serializationContext, reader, "dslVersion", typeof(global::System.Version), dslVersionStr);
}
}
}
}

CA2202 Warning from Code Analysis for OracleConnection disposal

We are getting the following warning from Code Analysis in Visual Studio 2010 and I'm wondering if this is a false positive that we can safely ignore or the code should be refactored to correctly dispose the object.
The relevant code:
public void MyFunction()
{
OracleConnection oraConnection = null;
OracleCommand oraCommand = null;
try
{
// Connect to the database
oraConnection = new OracleConnection(connectionString);
oraConnection.Open();
// Prepare and run the query
oraCommand = new OracleCommand(sqlQuery, oraConnection);
oraCommand.ExecuteNonQuery();
}
catch { throw; }
finally
{
// Perform a safe cleanup
if (oraCommand != null) { oraCommand.Dispose(); }
if (oraConnection != null)
{
oraConnection.Close();
oraConnection.Dispose();
}
}
}
The relevant error message:
Warning 18 CA2202 : Microsoft.Usage : Object 'oraConnection' can be disposed
more than once in method 'ClassName.MyFunction()'. To avoid generating a
System.ObjectDisposedException you should not call Dispose more than one
time on an object.
If you remove the line:
oraConnection.Close();
it should get rid of the warning, since closing and disposing a connection are essentially the same thing.
You might also want to replace your try/finally by a using statement.
Note that Microsoft's own guidelines say that IDisposable.Dispose should be implemented in such a way that it can safely be called multiple times. Which means that the CA2202 warning can safely be ignored, as noted in the comment by JoeM27 on the MSDN page for CA2202.

Resources