UWP application unable to access USB drive even though permissions are set - c#

I am working on an app that is responsible for formatting a USB drive and prepare it for further use on an embedded system.
I am formatting the drive using the following method that I found on stack overflow (unfortunately I did not save the link. I'll post it there if I find it again)
public static bool FormatUSB(string driveLetter, string fileSystem = "FAT32", bool quickFormat = true,
int clusterSize = 4096, string label = "USB_0000", bool enableCompression = false)
{
//add logic to format Usb drive
//verify conditions for the letter format: driveLetter[0] must be letter. driveLetter[1] must be ":" and all the characters mustn't be more than 2
if (driveLetter.Length != 2 || driveLetter[1] != ':' || !char.IsLetter(driveLetter[0]))
return false;
//query and format given drive
//best option is to use ManagementObjectSearcher
var files = Directory.GetFiles(driveLetter);
var directories = Directory.GetDirectories(driveLetter);
foreach (var item in files)
{
try
{
File.Delete(item);
}
catch (UnauthorizedAccessException) { }
catch (IOException) { }
}
foreach (var item in directories)
{
try
{
Directory.Delete(item);
}
catch (UnauthorizedAccessException) { }
catch (IOException) { }
}
ManagementObjectSearcher searcher = new ManagementObjectSearcher(#"select * from Win32_Volume WHERE DriveLetter = '" + driveLetter + "'");
foreach (ManagementObject vi in searcher.Get())
{
try
{
var completed = false;
var watcher = new ManagementOperationObserver();
watcher.Completed += (sender, args) =>
{
Console.WriteLine("USB format completed " + args.Status);
completed = true;
};
watcher.Progress += (sender, args) =>
{
Console.WriteLine("USB format in progress " + args.Current);
};
vi.InvokeMethod(watcher, "Format", new object[] { fileSystem, quickFormat, clusterSize, label, enableCompression });
while (!completed) { System.Threading.Thread.Sleep(1000); }
}
catch
{
}
}
return true;
}
I also added all the capabilities that should be required (I think) in order to access a removable drive in my manifest:
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10"
IgnorableNamespaces="uap mp rescap iot">
<Identity
Name="7b9becad-6afd-4872-bcb7-7f414c098edf"
Publisher="CN=vitto"
Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="7b9becad-6afd-4872-bcb7-7f414c098edf" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>DiskMakerApp</DisplayName>
<PublisherDisplayName>vitto</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="DiskMakerApp.App">
<uap:VisualElements
DisplayName="DiskMakerApp"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png"
Description="DiskMakerApp"
BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="broadFileSystemAccess" />
<rescap:Capability Name="appCaptureSettings" />
<Capability Name="internetClient" />
<uap:Capability Name="removableStorage" />
<iot:Capability Name="systemManagement"/>
<DeviceCapability Name="usb"/>
</Capabilities>
</Package>
And also allowed access to the file system in Window's settings page:
But I am still getting:
I am wondering if I am missing anything. Is there a way I could run the app as an administrator^ Would that solve the issue? (In any case, only admins would be able to run that app in a real life scenario)

UWP application unable to access USB drive even though permissions are set
Directory.GetFiles can't not use to access file with path in UWP platform. And you can only use Windows Storage API to access file with path (enable broadFileSystemAccess ), by the way, System.Management Namespace is not work for UWP platform, and if you want to format USB device within UWP app, please use desktop extension to process. for more please refer stefan' blog UWP with Desktop Extension

Related

Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) when trying to read battery of Airpod pro

I am trying to read my air pods pro battery life using UWP app and I get an exception error when socket.ConnectAsync is called Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) without any more info. Below you can find the source:
private async Task ConnectToAirpods()
{
DeviceInformationCollection connectedDevices = await DeviceInformation.FindAllAsync(BluetoothDevice.GetDeviceSelectorFromConnectionStatus(BluetoothConnectionStatus.Connected));
foreach (DeviceInformation connectedDevice in connectedDevices)
{
if (connectedDevice.Name != "AirPods Pro")
continue;
BluetoothDevice bluetoothDevice = await BluetoothDevice.FromIdAsync(connectedDevice.Id);
RfcommDeviceServicesResult rfcommServices = await bluetoothDevice.GetRfcommServicesForIdAsync(
RfcommServiceId.FromUuid(new Guid("0000111e-0000-1000-8000-00805f9b34fb")), BluetoothCacheMode.Uncached);
if (rfcommServices.Services.Count > 0)
{
var service = rfcommServices.Services[0];
try
{
var socket = new StreamSocket();
await socket.ConnectAsync(service.ConnectionHostName, service.ConnectionServiceName);
}
catch (Exception ex)
{
}
}
}
}
Update #1
Package.appxmanifest
<Capabilities>
<Capability Name="internetClient"/>
<Capability Name="internetClientServer"/>
<Capability Name="privateNetworkClientServer"/>
<DeviceCapability Name="bluetooth"/>
<DeviceCapability Name="bluetooth.rfcomm">
<Device Id="any">
<Function Type="name:serialPort"/>
</Device>
</DeviceCapability>
</Capabilities>
Update #2
<DeviceCapability Name="bluetooth.rfcomm">
<Device Id="any">
<Function Type="serviceId:0000111e-0000-1000-8000-00805f9b34fb" />
</Device>
</DeviceCapability>
I tested this. The problem may appear in this line of code:
RfcommDeviceServicesResult rfcommServices = await bluetoothDevice.GetRfcommServicesForIdAsync(RfcommServiceId.FromUuid(new Guid("0000111e-0000-1000-8000-00805f9b34fb")), BluetoothCacheMode.Uncached);
It is recommended to replace the Guid with:
RfcommDeviceServicesResult rfcommServices = await bluetoothDevice.GetRfcommServicesForIdAsync(
RfcommServiceId.FromUuid(RfcommServiceId.SerialPort.Uuid), BluetoothCacheMode.Uncached);
I used a similar wireless headset device for testing. Before the replacement, I got an access denied error. After that, the connection can proceed normally.
Thanks.

Showing PDF-File with MVVM Cross on Android and IOS

I want to open a PDF on the Phone via the File-Path but i cant figure out how i could do this properly without using 3rd party packages.
You have any suggestion for this?
I already tried to use this on Android:
public void OpenFile(string filePath)
{
var fileToOpen = new Java.IO.File(filePath);
var uri = FileProvider.GetUriForFile(Application.Context, Application.Context.PackageName + ".fileprovider", fileToOpen);
var intent = new Intent();
var mime = IOUtil.GetMimeType(uri.ToString());
intent.SetAction(Intent.ActionView);
intent.SetDataAndType(uri, mime);
intent.SetFlags(ActivityFlags.NewTask);
intent.AddFlags(ActivityFlags.GrantReadUriPermission);
Application.Context.StartActivity(intent);
}
But i get the following Error:
Unhandled Exception:
Java.Lang.NullPointerException: Attempt to invoke virtual method
'android.content.res.XmlResourceParser
android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager,
java.lang.String)' on a null object reference
first you should addd this code to your manifest file :
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.easyphotopicker.fileprovider"
android:exported="false"
android:grantUriPermissions="true"
tools:replace="android:authorities">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths"
tools:replace="android:resource"/>
</provider>
and create filepaths :
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<root-path name="root" path="" /> //root directory of the device new File("/");
<files-path name="files" path="" /> //context.getFilesDir()
<cache-path name="cache" path="" /> //context.getCacheDir()
<external-path name="external" path="" /> //Environment.getExternalStorageDirectory()
<external-files-path name="name" path="path" /> //context.getExternalFilesDirs()
<external-cache-path name="name" path="path" /> //getExternalCacheDirs()
</paths>
Your error is telling us that there is no file at the location matching that's passed into the function. There's a few ways of doing this, one of them is as shown. After accepting permissions to access folders and files, this should be one of the simplest ways. You seem to be close:
public void OpenPdfFile(string filename)
{
var f = new Java.IO.File(filename);
if (f.Exists())
{
System.Diagnostics.Debug.WriteLine("File exists!");
try
{
var openFileIntent = new Intent(Intent.ActionView);
openFileIntent.SetDataAndType(Android.Net.Uri.FromFile(f), "application/pdf");
openFileIntent.SetFlags(ActivityFlags.NoHistory);
StartActivity(Intent.CreateChooser(openFileIntent, "Open pdf file"));
}
catch (ActivityNotFoundException)
{
//handle when no available apps
}
}
}
I haven't tested your work, but the first thing would be to see if you added this to the Manifest file
android:authorities="com.{package}.{name}.fileprovider"
since your code says Application.Context.PackageName + ".fileprovider"

UWP/C#/IoT/RPi: Access USB Device (Stick) from Win IoT on RPi AND Copy to KnownFolders

Here is my challenge:
Windows IoT on Raspi, C# UWP-App
On Boot or klick...
Enumerate connected USB devices
Select the USB Stick
Enumerate Fiels and folders on the stick
If a certain folder name is found, copy folder as-is to KnownFolders.Documents
It is astonishing that there are many half solutions on the web but none of them hardly works.
Some things I tried:
var removableDeviceList = await KnownFolders.RemovableDevices.GetFoldersAsync();
if (removableDeviceList.Count > 0)
{
StorageFolder targetDevice = removableDeviceList.FirstOrDefault();
ListBox.Items.Add(targetDevice.Name);
}
Works so far but stuck afterwards.
And yes, functions like Picture library, file definitions, removable devices are activated in the manifest. I can't believe that this basic thing is really such a difficult task to solve?
There is an example I test on Raspberry Pi 3 with Windows 10 IoT Core. It works for me.
Source folder: test folder in USB drive root(E:\test). There are three files: hello.txt, welcome1.png, welcome3.jpg .
Destination folder: KnownFolders.DocumentsLibrary root folder.
The following code complete copy files in test folder to KnownFolders.DocumentsLibrary root folder.
public async void USBDriveCopyFolder()
{
var targetFolderName = "test";
var removableDevice = (await KnownFolders.RemovableDevices.GetFoldersAsync()).FirstOrDefault();
if (null == removableDevice)
{
System.Diagnostics.Debug.WriteLine("removableDevice is null !");
return;
}
System.Diagnostics.Debug.WriteLine(removableDevice.Name + ":\n");
var sourceFolder = await removableDevice.GetFolderAsync(targetFolderName);
if (null == sourceFolder)
{
System.Diagnostics.Debug.WriteLine(targetFolderName + " folder is not found !");
return;
}
System.Diagnostics.Debug.WriteLine(sourceFolder.Name + ":\n");
var destFodler = KnownFolders.DocumentsLibrary;
if (null == destFodler)
{
System.Diagnostics.Debug.WriteLine("KnownFolders.DocumentsLibrary folder get failed !");
return;
}
var files = await sourceFolder.GetFilesAsync();
foreach (var file in files)
{
System.Diagnostics.Debug.WriteLine(file.Name + "\n");
await file.CopyAsync(destFodler);
}
}
Device capabilities in package.appxmanifest:
<Applications>
...
...
<Application>
<Extensions>
<uap:Extension Category="windows.fileTypeAssociation">
<uap:FileTypeAssociation Name="txt">
<uap:SupportedFileTypes>
<uap:FileType>.txt</uap:FileType>
</uap:SupportedFileTypes>
</uap:FileTypeAssociation>
</uap:Extension>
<uap:Extension Category="windows.fileTypeAssociation">
<uap:FileTypeAssociation Name="jpg">
<uap:SupportedFileTypes>
<uap:FileType>.jpg</uap:FileType>
</uap:SupportedFileTypes>
</uap:FileTypeAssociation>
</uap:Extension>
<uap:Extension Category="windows.fileTypeAssociation">
<uap:FileTypeAssociation Name="png">
<uap:SupportedFileTypes>
<uap:FileType>.png</uap:FileType>
</uap:SupportedFileTypes>
</uap:FileTypeAssociation>
</uap:Extension>
</Extensions>
</Application>
</Applications>
<Capabilities>
<uap:Capability Name="picturesLibrary" />
<uap:Capability Name="removableStorage" />
<uap:Capability Name="documentsLibrary" />
</Capabilities>

Error while accessing AvailableFreeSpace/TotalSize in DriveInfo in UWP

I am able to list the local disks using DriveInfo.GetDrives() method. also, I access/get the Drive name using Name property. But I get error as "System. UnauthorizedAccess Exception: 'Access to the path 'X:\' is denied." while accessing any properties like AvailableFreeSpace. Code below.
DriveInfo[] allDrives = DriveInfo.GetDrives();
foreach (DriveInfo d in allDrives)
{
Debug.WriteLine("Drive: " + d.Name); //This line executes w/o error!
Debug.WriteLine("Drive: " + d.AvailableFreeSpace);
Debug.WriteLine("Drive: " + d.TotalSize);
}
NB: I have placed the following lines xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" in Package Tag Block and < rescap:Capability Name="broadFileSystemAccess"/ > inside the Capabilities Tag Block, in Package.appxmanifest file in my Project.
I am able to get total and available disk space for some of my drives using this code:
const String k_freeSpace = "System.FreeSpace";
const String k_totalSpace = "System.Capacity";
DriveInfo[] allDrives = DriveInfo.GetDrives();
foreach (DriveInfo d in allDrives)
{
try
{
Debug.WriteLine("Drive: " + d.Name);
Debug.WriteLine("RootDir: " + d.RootDirectory.FullName);
StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(d.RootDirectory.FullName);
var props = await folder.Properties.RetrievePropertiesAsync(new string[] { k_freeSpace, k_totalSpace });
Debug.WriteLine("FreeSpace: " + (UInt64)props[k_freeSpace]);
Debug.WriteLine("Capacity: " + (UInt64)props[k_totalSpace]);
}
catch (Exception ex)
{
Debug.WriteLine(String.Format("Couldn't get info for drive {0}. Does it have media in it?", d.Name));
}
}
I am targeting Windows 10, version 1803 (10.0: Build 17134) for both my "Min version" and "Target version".
Here are a couple of excerpts from my Package.appxmanifest
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap mp iot rescap">
...
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="broadFileSystemAccess" />
</Capabilities>
</Package>

UWP DeviceWatcher skips from Created to EnumerationComplete

I've written a UWP class library that doesn't seem to scan for BLE devices. Looking at the DeviceWatcher, it skips from the status Created to EnumerationComplete. I've tried creating a manifest for my library but the issue persists. Below is some of the code, and my manifest.
Adapter.cs
private DeviceWatcher deviceWatcher;
public override IList<IDevice> ConnectedDevices => ConnectedDeviceRegistry.Values.ToList();
/// <summary>
/// Used to store all connected devices
/// </summary>
public Dictionary<string, IDevice> ConnectedDeviceRegistry { get; }
/// <summary>
/// Registry used to store device instances for pending operations : connect
/// </summary>
public Dictionary<string, IDevice> DeviceOperationRegistry { get; }
public Adapter(DeviceWatcher deviceWatcher)
{
Platform = PLATFORM.WINDOWS;
DeviceOperationRegistry = new Dictionary<string, IDevice>();
ConnectedDeviceRegistry = new Dictionary<string, IDevice>();
this.deviceWatcher = deviceWatcher;
/*DeviceInformation.CreateWatcher(
aqsAllBluetoothLEDevices,
requestedProperties,
DeviceInformationKind.AssociationEndpoint);*/
deviceWatcher.Added += DeviceWatcher_Added;
deviceWatcher.Updated += DeviceWatcher_Updated;
deviceWatcher.Removed += DeviceWatcher_Removed;
deviceWatcher.EnumerationCompleted += DeviceWatcher_EnumerationCompleted;
deviceWatcher.Stopped += DeviceWatcher_Stopped;
}
protected override Task StartScanningForDevicesNativeAsync(Guid[] serviceUuids, bool allowDuplicatesKey, CancellationToken scanCancellationToken)
{
// clear out the list
DiscoveredDevices.Clear();
deviceWatcher.Start();
return Task.FromResult(true);
}
BleImplementation.cs
string[] requestedProperties = { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected", "System.Devices.Aep.Bluetooth.Le.IsConnectable" };
// BT_Code: Example showing paired and non-paired in a single query.
string aqsAllBluetoothLEDevices = "(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")";
DeviceWatcher deviceWatcher;
protected override IAdapter CreateNativeAdapter()
{
deviceWatcher = DeviceInformation.CreateWatcher(
aqsAllBluetoothLEDevices,
requestedProperties,
DeviceInformationKind.AssociationEndpoint);
return new Adapter(deviceWatcher);
}
Package.appxmanifest
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest">
<Prerequisites>
<OSMinVersion></OSMinVersion>
<OSMaxVersionTested></OSMaxVersionTested>
</Prerequisites>
<Resources>
<Resource Language="" />
</Resources>
<Applications>
<Application Id="" StartPage="">
<VisualElements DisplayName="" Description=""
Logo="" SmallLogo=""
ForegroundText="" BackgroundColor="">
<SplashScreen Image="" />
</VisualElements>
</Application>
</Applications>
<Identity Name="MyCompany.MySuite.MyApp"
Version="1.0.0.0"
Publisher="CN=MyCompany, O=MyCompany, L=MyCity, S=MyState, C=MyCountry"/>
<Properties>
<DisplayName>MyApp</DisplayName>
<PublisherDisplayName>MyCompany</PublisherDisplayName>
<Logo>images\icon.png</Logo>
</Properties>
<Capabilities>
<Capability Name="internetClient" />
<!--BT_Code: Always declare the bluetooth capability when using Bluetooth-->
<DeviceCapability Name="bluetooth" />
</Capabilities>
</Package>

Categories

Resources