Fetch Azure sync table on new device - c#

I have an Azure app service setup for SyncTables. On my development machine, I can save items and they sync to the cloud, no problem. However, I am having a hard time getting the data to a new device. I assumed that when first loading the application on the new device that the table.PullAsync() calls would fetch all the data for each table.
The push/pull process completes successfully, but no data is pulled to the device. I can add a new item on the new device, and it uploads to the cloud, but I am not having any luck getting the initial data onto the new device. Here is my SyncAsync method:
private IMobileServiceSyncTable<Person> personTable = App.MobileService.GetSyncTable<Person>();
private IMobileServiceSyncTable<Card> cardTable = App.MobileService.GetSyncTable<Card>();
private async Task SyncAsync(bool showMessage)
{
string errorString = null;
try
{
await App.MobileService.SyncContext.PushAsync();
await personTable.PullAsync("person", personTable.CreateQuery());
await cardTable.PullAsync("cards", cardTable.CreateQuery());
}
catch (MobileServicePushFailedException ex)
{
errorString = "Push failed because of sync errors: " +
ex.PushResult.Errors.Count + " errors, message: " + ex.Message;
errorString = ex.PushResult.Errors.Aggregate(errorString, (current, error) => current + ("\r\n" + error.Result));
}
catch (Exception ex)
{
errorString = "Pull failed: " + ex.Message +
"\n\nIf you are still in an offline scenario, " +
"you can try your Pull again when connected with your Mobile Service.";
}
if (errorString != null)
{
// TODO: log some sort of error message
MessageBox.Show(errorString);
}
else
{
if (showMessage)
{
MessageBox.Show("Database synchronization complete.");
}
LastSynced = string.Format("Last Synced: {0}", DateTime.Now.ToString());
}
}
As I said, new data created will sync to the new device, but I need to be able to do an initial pull of the data when the application is installed on a new device. Is there a way to force the PullAsync() call to fetch all data, or somehow to make the SyncTables know that they have data to fetch so that the next time SyncAsync is called, they will fetch the data?
Here is my InitLocalStoreAsync() method, which initializes the local database on application launch. I have also tried deleting the localstore.db file and launching again, hoping that the fresh copy of the file would want to pull all the data, but that wasn't the case.
private async Task InitLocalStoreAsync()
{
if (!MobileService.SyncContext.IsInitialized)
{
var store = new MobileServiceSQLiteStore("localstore.db");
store.DefineTable<Person>();
store.DefineTable<Card>();
await MobileService.SyncContext.InitializeAsync(store);
}
}
EDIT
One thing I'm thinking is that maybe for now I will have to make sure all instances of the software are installed before adding any data, but I want to get this figured out in case of adding more installations in the future.
EDIT 2
I tried to fetch the data from the remote database manually and import it into the new installation, but that caused the items to be duplicated on the server after the next sync.
EDIT 3
Installing multiple instances prior to adding any data also did not work. Both instances can push data to the remote server, but neither are fetching the new data as they should. I'm hoping that it is something simple like a setting somewhere, but I don't have this problem with another Azure app service that I'm running.

The problem ended up being that I was trying to use the old NuGet packages WindowsAzure.MobileServices and WindowsAzure.MobileServices.SQLiteStore. Changing to use the new Microsoft.Azure.Mobile.Client and Microsoft.Azure.Mobile.Client.SQLiteStore packages got everything working properly.
One of the things that is different is that the new Azure system properties no longer contain the leading __ so the old packages didn't know how to compare what data was new on the server.

Related

Access Denied status getting custom service's characteristics with GetCharacteristicsAsync

I'm attempting to get the characteristics of a custom BLE service. I have a NETStandard class library, making use of NETCore build 17134 for Bluetooth communication. This library is then used in a WPF application (.NET Framework 4.7.1.) I'm able to connect to my BLE peripheral, as well as read the generic service that includes Hardware Revision, etc. However, when it then goes to get the characteristics of my custom service, the status reads AccessDenied and the array of characteristics is empty. Any help would be greatly appreciated.
The same code works when it's purely UWP. However, I have no way to set Bluetooth permissions in the desktop app as I can in UWP. I've attempted running as administrator and performing the workaround using an AppID/registry entry. It didn't seem to work, but perhaps I simply did something wrong.
Is this a known issue? I've read there's been some regression since the original Creator's Update (15xxx) but the threads all seem about a year old.
protected async override Task<IList<ICharacteristic>> GetCharacteristicsNativeAsync()
{
var accessRequestResponse = await _nativeService.RequestAccessAsync();
// Returns Allowed
if (accessRequestResponse != Windows.Devices.Enumeration.DeviceAccessStatus.Allowed)
{
throw new Exception("Access to service " + _nativeService.Uuid.ToString() + " was disallowed w/ response: " + accessRequestResponse);
}
var allCharacteristics = await _nativeService.GetCharacteristicsAsync(Windows.Devices.Bluetooth.BluetoothCacheMode.Uncached);
// Status: AccessDenied
var status = allCharacteristics.Status;
// No error
var err = allCharacteristics.ProtocolError;
var nativeChars = allCharacteristics.Characteristics;
var charList = new List<ICharacteristic>();
foreach (var nativeChar in nativeChars)
{
var characteristic = new Characteristic(nativeChar, this);
charList.Add(characteristic);
}
return charList;
}
Any help would be greatly appreciated!

how to get real time log via perforce api similar to p4v log

I am facing issue with perforce api (.net), as i am unable to pull sync logs in real time.
- What am I trying to do
I am trying to pull real time logs as Sync is triggered using the
Perforce.P4.Client.SyncFiles() command. Similar to the P4V GUI Logs, which update when we try to sync any files.
- What is happening now
As the output is generated only after the command is done execution its not something intended for.
Also tried looking into Perforce.P4.P4Server.RunCommand() which does provide detailed report but only after the execution of the command.
Looked into this
Reason is -
I am trying to add a status update to the Tool i am working on which shows which Perforce file is currently being sync'd.
Please advise. Thanks in Advance.
-Bharath
In the C++ client API (which is what P4V is built on), the client receives an OutputInfo callback (or OutputStat in tagged mode) for each file as it begins syncing.
Looking over the .NET documentation I think the equivalents are the P4CallBacks.InfoResultsDelegate and P4CallBacks.TaggedOutputDelegate which handle events like P4Server.InfoResultsReceived etc.
I ended up with the same issue, and I struggled quite a bit to get it to work, so I will share the solution I found:
First, you should use the P4Server class instead of the Perforce.P4.Connection. They are two classes doing more or less the same thing, but when I tried using the P4.Connection.TaggedOutputReceived events, I simply got nothing back. So instead I tried with the P4Server.TaggedOutputReceived, and there, finally, I got the TaggedOutput just like I wanted.
So, here is a small example:
P4Server p4Server = new P4Server(cwdPath); //In my case I use P4Config, so no need to set user or to login, but you can do all that with the p4Server here.
p4Server.TaggedOutputReceived += P4ServerTaggedOutputEvent;
p4Server.ErrorReceived += P4ServerErrorReceived;
bool syncSuccess=false;
try
{
P4Command syncCommand = new P4Command(p4Server, "sync", true, syncPath + "\\...");
P4CommandResult rslt = syncCommand.Run();
syncSuccess=true;
//Here you can read the content of the P4CommandResult
//But it will only be accessible when the command is finished.
}
catch (P4Exception ex) //Will be caught only when the command has failed
{
Console.WriteLine("P4Command failed: " + ex.Message);
}
And the method to handle the error messages or the taggedOutput:
private void P4ServerErrorReceived(uint cmdId, int severity, int errorNumber, string data)
{
Console.WriteLine("P4ServerErrorReceived:" + data);
}
private void P4ServerTaggedOutputEvent(uint cmdId, int ObjId, TaggedObject Obj)
{
Console.WriteLine("P4ServerTaggedOutputEvent:" + Obj["clientFile"]); //Write the synced file name.
//Note that I used this only for a 'Sync' command, for other commands, I guess there might not be any Obj["clientFile"], so you should check for that.
}

Pushing DataBase to PDA results in empty database with RAPI2

I have a WorkAboutPro 4 and on this i run an application.
This application uses an SQLlite database.
Now i also run a computer program along side it, in here i use RAPI2 to work with my handheld device.
As soon i connect my device a function triggers and it first pulls my database from my handheld to my computer.
I then do some stuff with it and go on to push it back. problem is that the database that returns is always 0kb and has no data, not even tables.
//Create my Paths
string myDevice = device.GetFolderPath(SpecialFolder.ProgramFiles);
string deviceFile = myDevice + #"\PPPM\SQL_PPPM.s3db";
string myComputer = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Substring(6);
string localFile = myComputer + #"\SQL_PPPM.s3db";
//Get the Database
RemoteFile.CopyFileFromDevice(device, deviceFile, localFile, true);
//Do Stuff
try
....
catch(Exception ex)
....
//Push The Database back
RemoteFile.CopyFileToDevice(device, localFile, deviceFile, true);
Now first i thought it was beccause i am not able to push a database over the connection. So i tried to pull a full database to my computer. but this works just fine.
Then i went on and placed an empty Txt file on my hadn held. pulled it, added text and pushed it and also this works fine.
So the only thing that goes wrong is when i try i push a full database back to my HandHeld resulting in an 0kb empty database.
Anyone an idea why this is?
Lotus~
Edit: if you know a beter way to detect if a device is connected and push/pull files from a PDA please let me know.
So i faced the same problem as well.
It most likely has to do with your Sqlite connections still being open.
The thing that worked out best for me was to modify my SqlDataAccess class and start using the 'using'.
Example:
using(var connection = new SQLiteConnection(ConnectionString))
{
try
{
connection.Open();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
finally
{
connection.Close();
}
}
For me the same worked with DataAdapters.
Good luck in the future, and remember never throw yourself in a case of Denvercoder9. You should have answered this a long time ago.

How do i reset the system cache of WLAN info?

I am trying to write a WLAN fingerprinting program using NativeWifi in C#. To do this i run a loop to get the wlan information many times and then later use matlab to average / analyze the data.
The problem is that i get all the same values, even as i move about the house, when the program is running. From the internet i've seen that there is a cache that stores the data of available networks. I was wondering if there is a system call which resets this cache.
I have also seen this using the cmd call
netsh wlan show networks mode=bssid
this gives me the same values until i open the available wifi networks in my OS and if i run it again after, it will give different values.
edit: This system will be for my use only, so i would be comfortable starting over on a linux platform if there is a known library that can handle this for me. I don't even know what to google to even get the information, though. Anything related to "network cache" takes me to help threads of unrelated topics...
I will provide the relevant part of my code below:
public void get_info_instance(StreamWriter file)
{
try
{
foreach (WlanClient.WlanInterface wlanIface in client.Interfaces)
{
Wlan.WlanBssEntry[] wlanBssEntries = wlanIface.GetNetworkBssList();
foreach (Wlan.WlanBssEntry network in wlanBssEntries)
{
int rss = network.rssi;
byte[] macAddr = network.dot11Bssid;
string tMac = "";
for (int i = 0; i < macAddr.Length; i++)
{
tMac += macAddr[i].ToString("x2").PadLeft(2, '0').ToUpper();
}
file.WriteLine("Found network: " + System.Text.ASCIIEncoding.ASCII.GetString(network.dot11Ssid.SSID).ToString());
file.WriteLine("Signal: " + network.linkQuality + "%");
file.WriteLine("BSS Type: " + network.dot11BssType + ".");
file.WriteLine("RSSID: " + rss.ToString());
file.WriteLine("BSSID: " + tMac);
file.WriteLine(" ");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Internally, netsh is powered by this API. What this means, is that calling netsh wlan show networks mode=bssid just returns the cache of the networks that showed up during the last scan. This is what you've discovered.
This means that in order to refresh this cache, you need to trigger a scan. If your C# library you are using includes it, you could make this happen on demand with a call to WlanScan. I am not sure which C# wrapper you are using, but it probably includes this function. When you get a scan complete notification (register with source WLAN_NOTIFICATION_SOURCE_ACM and look out for wlan_notification_acm_scan_list_refresh), the cache should be updated.
If you let me know which C# library you are using, maybe I can point you to the relevant functions.
You mentioned that opening the available networks causes the cache to refresh. This is because opening the available networks triggers a call to WlanScan.
Profiles are not relevant to the available network list -- profiles are what the Wlan service uses to keep track of which networks are configured on your machine -- deleting them does not make WlanSvc scan again. It may be a coincidence that deleting them happens to coincide with a scan, but it is more of a side effect than the designed usage.
edit: to subscribe to notifications using the Managed Wifi API you are using, this snippet should work:
wlanIface.WlanNotification += wlanIface_WlanNotification;
And the callback:
static void wlanIface_WlanNotification(Wlan.WlanNotificationData notifyData)
{
if (notifyData.notificationCode == (int)Wlan.WlanNotificationCodeAcm.ScanComplete)
{
Console.WriteLine("Scan Complete!");
}
}
You can test this by running this, then opening the available networks on Windows. You should see "Scan Complete" shortly after you open it each time. You can use a messagebox instead of Console.WriteLine if you prefer.
To trigger a scan yourself:
wlanIface.Scan();
for all
netsh wlan delete profile name=* i=*
you might not want to do it on all interfaces, and hard code the interface in there for faster result

Open "Windows Update" screen and execute "Check for updates" from code C# [duplicate]

Is there any API for writing a C# program that could interface with Windows update, and use it to selectively install certain updates?
I'm thinking somewhere along the lines of storing a list in a central repository of approved updates. Then the client side applications (which would have to be installed once) would interface with Windows Update to determine what updates are available, then install the ones that are on the approved list. That way the updates are still applied automatically from a client-side perspective, but I can select which updates are being applied.
This is not my role in the company by the way, I was really just wondering if there is an API for windows update and how to use it.
Add a Reference to WUApiLib to your C# project.
using WUApiLib;
protected override void OnLoad(EventArgs e){
base.OnLoad(e);
UpdateSession uSession = new UpdateSession();
IUpdateSearcher uSearcher = uSession.CreateUpdateSearcher();
uSearcher.Online = false;
try {
ISearchResult sResult = uSearcher.Search("IsInstalled=1 And IsHidden=0");
textBox1.Text = "Found " + sResult.Updates.Count + " updates" + Environment.NewLine;
foreach (IUpdate update in sResult.Updates) {
textBox1.AppendText(update.Title + Environment.NewLine);
}
}
catch (Exception ex) {
Console.WriteLine("Something went wrong: " + ex.Message);
}
}
Given you have a form with a TextBox this will give you a list of the currently installed updates. See http://msdn.microsoft.com/en-us/library/aa387102(VS.85).aspx for more documentation.
This will, however, not allow you to find KB hotfixes which are not distributed via Windows Update.
The easiest way to do what you want is using WSUS. It's free and basically lets you setup your own local windows update server where you decide which updates are "approved" for your computers. Neither the WSUS server nor the clients need to be in a domain, though it makes it easier to configure the clients if they are. If you have different sets of machines that need different sets of updates approved, that's also supported.
Not only does this accomplish your stated goal, it saves your overall network bandwidth as well by only downloading the updates once from the WSUS server.
If in your context you're allowed to use Windows Server Update Service (WSUS), it will give you access to the Microsoft.UpdateServices.Administration Namespace.
From there, you should be able to do some nice things :)
P-L right. I tried first the Christoph Grimmer-Die method, and in some case, it was not working. I guess it was due to different version of .net or OS architecture (32 or 64 bits).
Then, to be sure that my program get always the Windows Update waiting list of each of my computer domain, I did the following :
Install a serveur with WSUS (may save some internet bandwith) : http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=5216
Add all your workstations & servers to your WSUS server
Get SimpleImpersonation Lib to run this program with different admin right (optional)
Install only the administration console component on your dev workstation and run the following program :
It will print in the console all Windows updates with UpdateInstallationStates.Downloaded
using System;
using Microsoft.UpdateServices.Administration;
using SimpleImpersonation;
namespace MAJSRS_CalendarChecker
{
class WSUS
{
public WSUS()
{
// I use impersonation to use other logon than mine. Remove the following "using" if not needed
using (Impersonation.LogonUser("mydomain.local", "admin_account_wsus", "Password", LogonType.Batch))
{
ComputerTargetScope scope = new ComputerTargetScope();
IUpdateServer server = AdminProxy.GetUpdateServer("wsus_server.mydomain.local", false, 80);
ComputerTargetCollection targets = server.GetComputerTargets(scope);
// Search
targets = server.SearchComputerTargets("any_server_name_or_ip");
// To get only on server FindTarget method
IComputerTarget target = FindTarget(targets, "any_server_name_or_ip");
Console.WriteLine(target.FullDomainName);
IUpdateSummary summary = target.GetUpdateInstallationSummary();
UpdateScope _updateScope = new UpdateScope();
// See in UpdateInstallationStates all other properties criteria
_updateScope.IncludedInstallationStates = UpdateInstallationStates.Downloaded;
UpdateInstallationInfoCollection updatesInfo = target.GetUpdateInstallationInfoPerUpdate(_updateScope);
int updateCount = updatesInfo.Count;
foreach (IUpdateInstallationInfo updateInfo in updatesInfo)
{
Console.WriteLine(updateInfo.GetUpdate().Title);
}
}
}
public IComputerTarget FindTarget(ComputerTargetCollection coll, string computername)
{
foreach (IComputerTarget target in coll)
{
if (target.FullDomainName.Contains(computername.ToLower()))
return target;
}
return null;
}
}
}

Categories