Is there a method available for UWP apps to get available disk space - c++

I am working on a UWP app that depends on available storage space, and would like to have that information prior to a save fail. I have tried the RetrievePropertiesAsync calls on the known folders, but do not get a Freespace or Capacity property in the resultant list. Is there a method available for this?
Code used to access properties:
auto basicProperties = co_await videosFolder->GetBasicPropertiesAsync();
auto retrievedProperties = co_await basicProperties->RetrievePropertiesAsync(propertiesToRetrieve);
unsigned long freeSpace = retrievedProperties->Size;
auto it = retrievedProperties->First();
bool validData = (it != nullptr);
while (validData)
{
String^ text = it->Current->Key;
validData = it->MoveNext();
}

Related

Using Vulkan memory allocator with Volk

I'm currently trying to use Vulkan memory allocator with the meta loader Volk
here is the link of the two: https://github.com/zeux/volk
https://gpuopen.com/vulkan-memory-allocator/
But I have trouble with creating the VmaAllocator, here is my code:
void VulkApp::Init(PipelineFlags t_Conf, entt::registry& t_reg)
{
volkInitialize();
WindowProps props = {};
props.Height = 600;
props.Width = 800;
props.Title = "Engine";
currentWindow = EngWindow::Create(props);
//Create all physical, logical, instance for vulkan
Prepare();
VolkDeviceTable test;
volkLoadDeviceTable(&test, m_LogicalDevice->GetVkDevice());
VmaAllocatorCreateInfo allocatorCreateInfo = {};
allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2;
allocatorCreateInfo.physicalDevice = m_PhysicalDevice->GetVkPhysicalDevice();
allocatorCreateInfo.device = m_LogicalDevice->GetVkDevice();
allocatorCreateInfo.instance = m_Instance->GetRawVkInstance();
allocatorCreateInfo.pVulkanFunctions = reinterpret_cast<const VmaVulkanFunctions*> (&test);
VmaAllocator allocator;
vmaCreateAllocator(&allocatorCreateInfo, &allocator);
BuildRenderPipelines(t_Conf, t_reg);
}
void VulkApp::Prepare()
{
m_Instance = std::make_unique<VulkInst>();
volkLoadInstance(m_Instance->GetRawVkInstance());
currentWindow->CreateSurface(m_Instance->GetRawVkInstance(), &m_Surface);
m_PhysicalDevice = std::make_unique<PhysicalDevice>(*m_Instance);
m_LogicalDevice = std::make_unique<LogicalDevice>(*m_Instance, *m_PhysicalDevice, m_Surface);
volkLoadDevice(m_LogicalDevice->GetVkDevice());
m_SwapChain = std::make_unique<SwapChain>(ChooseSwapExtent(), *m_LogicalDevice, *m_PhysicalDevice, m_Surface);
GraphicsHelpers::CreateCommandPool(m_CommandPool, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); //TODO: added Transient bit
CreateFrameSyncResources();
/*
Create Camera
*/
BuildSwapChainResources();
}
I don't have any error when i build, but when i execute, the VmaCreateAllocator return an error:
Exception raised at 0x00007FFAB0CD836B (VkLayer_khronos_validation.dll) in My_Game.exe : 0xC0000005 : access violation reading location 0x0000000000000120.
Not very useful, but it stops on the line 14082 of the file vk_mem_alloc.h:
(*m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties)(m_PhysicalDevice, &m_MemProps);
The program check all the vulkan validation function so my vulkan function table must be good. But still the allocation fail.
I'm sorry i don't put a 'minimal' code, but with vulkan, even the minimum is really long. So, as a first test, maybe some of you have an insight of the error?
If you use a loader like Volk, you need to provide all memory related Vulkan function pointers used by VMA yourself.
This is done via the pVulkanFunctions member of the VmaAllocatorCreateInfo structure.
So when creating your VmaAllactor you set the function pointer in that to those fetched via Volk like this:
VmaVulkanFunctions vma_vulkan_func{};
vma_vulkan_func.vkAllocateMemory = vkAllocateMemory;
vma_vulkan_func.vkBindBufferMemory = vkBindBufferMemory;
vma_vulkan_func.vkBindImageMemory = vkBindImageMemory;
vma_vulkan_func.vkCreateBuffer = vkCreateBuffer;
vma_vulkan_func.vkCreateImage = vkCreateImage;
vma_vulkan_func.vkDestroyBuffer = vkDestroyBuffer;
vma_vulkan_func.vkDestroyImage = vkDestroyImage;
vma_vulkan_func.vkFlushMappedMemoryRanges = vkFlushMappedMemoryRanges;
vma_vulkan_func.vkFreeMemory = vkFreeMemory;
vma_vulkan_func.vkGetBufferMemoryRequirements = vkGetBufferMemoryRequirements;
vma_vulkan_func.vkGetImageMemoryRequirements = vkGetImageMemoryRequirements;
vma_vulkan_func.vkGetPhysicalDeviceMemoryProperties = vkGetPhysicalDeviceMemoryProperties;
vma_vulkan_func.vkGetPhysicalDeviceProperties = vkGetPhysicalDeviceProperties;
vma_vulkan_func.vkInvalidateMappedMemoryRanges = vkInvalidateMappedMemoryRanges;
vma_vulkan_func.vkMapMemory = vkMapMemory;
vma_vulkan_func.vkUnmapMemory = vkUnmapMemory;
vma_vulkan_func.vkCmdCopyBuffer = vkCmdCopyBuffer;
And then pass those to the create info:
VmaAllocatorCreateInfo allocator_info{};
...
allocator_info.pVulkanFunctions = &vma_vulkan_func;

C++/CX - DataReader out of bounds exception

I have the following code which opens a file and it works most of the time for one time. After that I get exceptions thrown and I don't know where the problem is hiding. I tried to look for this for a couple of days already but no luck.
String^ xmlFile = "Assets\\TheXmlFile.xml";
xml = ref new XmlDocument();
StorageFolder^ InstallationFolder = Windows::ApplicationModel::Package::Current->InstalledLocation;
task<StorageFile^>(
InstallationFolder->GetFileAsync(xmlFile)).then([this](StorageFile^ file) {
if (nullptr != file) {
task<Streams::IRandomAccessStream^>(file->OpenAsync(FileAccessMode::Read)).then([this](Streams::IRandomAccessStream^ stream)
{
IInputStream^ deInputStream = stream->GetInputStreamAt(0);
DataReader^ reader = ref new DataReader(deInputStream);
reader->InputStreamOptions = InputStreamOptions::Partial;
reader->LoadAsync(stream->Size);
strXml = reader->ReadString(stream->Size);
MessageDialog^ dlg = ref new MessageDialog(strXml);
dlg->ShowAsync();
});
}
});
The error is triggered at this part of the code:
strXml = reader->ReadString(stream->Size);
I get the following error:
First-chance exception at 0x751F5B68 in XmlProject.exe: Microsoft C++ exception: Platform::OutOfBoundsException ^ at memory location 0x02FCD634. HRESULT:0x8000000B The operation attempted to access data outside the valid range
WinRT information: The operation attempted to access data outside the valid range
Just like I said, the first time it just works but after that I get the error. I tried detaching the stream and buffer of the datareader and tried to flush the stream but no results.
I've also asked this question on the Microsoft C++ forums and credits to the user "Viorel_" I managed to get it working. Viorel said the following:
Since LoadAsync does not perform the operation immediately, you should probably add a corresponding “.then”. See some code: https://social.msdn.microsoft.com/Forums/windowsapps/en-US/94fa9636-5cc7-4089-8dcf-7aa8465b8047. This sample uses “create_task” and “then”: https://code.msdn.microsoft.com/vstudio/StreamSocket-Sample-8c573931/sourcecode (file Scenario1.xaml.cpp, for example).
I have had to separate the content in the task<Streams::IRandomAccessStream^> and split it up in separate tasks.
I reconstructed my code and I have now the following:
String^ xmlFile = "Assets\\TheXmlFile.xml";
xml = ref new XmlDocument();
StorageFolder^ InstallationFolder = Windows::ApplicationModel::Package::Current->InstalledLocation;
task<StorageFile^>(
InstallationFolder->GetFileAsync(xmlFile)).then([this](StorageFile^ file) {
if (nullptr != file) {
task<Streams::IRandomAccessStream^>(file->OpenAsync(FileAccessMode::Read)).then([this](Streams::IRandomAccessStream^ stream)
{
IInputStream^ deInputStream = stream->GetInputStreamAt(0);
DataReader^ reader = ref new DataReader(deInputStream);
reader->InputStreamOptions = InputStreamOptions::Partial;
create_task(reader->LoadAsync(stream->Size)).then([reader, stream](unsigned int size){
strXml = reader->ReadString(stream->Size);
MessageDialog^ dlg = ref new MessageDialog(strXml);
dlg->ShowAsync();
});
});
}
});

Update function broken in C++ Azure Mobile Library

I am trying to update a record in one of my Azure Mobile tables using the “update” function in the azure mobile C++ header. But I get an exception. Below is what my code looks like:
void DBUtils::DBQuestion::UpdateQuestionInTable(std::shared_ptr<azure::mobile::table> table)
{
auto obj = json::value::object();
obj[U("id")] = json::value::string(ID);
obj[U("QuestionText")] = json::value::string(QuestionText);
obj[U("AnswerLatitude")] = json::value::number(AnswerLatitude);
obj[U("AnswerLongitude")] = json::value::number(AnswerLongitude);
table->update(obj);
}
I have verified that the ID above is a valid one actually present in the table. A similar insert operation (which doesn’t specify the ID field) actually succeeds:
void DBUtils::DBQuestion::InsertIntoTable(std::shared_ptr<azure::mobile::table> table)
{
auto obj = json::value::object();
obj[U("QuestionText")] = json::value::string(QuestionText);
obj[U("AnswerLatitude")] = json::value::number(AnswerLatitude);
obj[U("AnswerLongitude")] = json::value::number(AnswerLongitude);
table->insert(obj);
}
What am I doing wrong?
Azure Mobile recently updated its table schema so that the Id field is now a string, which gets filled in by the server with a Guid value if the client doesn’t set it.
This change has introduced a bug in the C++ library. As a workaround, you can try calling the other overload for update, the one that takes the ID string and the object.
void DBUtils::DBQuestion::UpdateQuestionInTable(utility::string_t id, std::shared_ptr<azure::mobile::table> table)
{
auto obj = json::value::object();
obj[U("QuestionText")] = json::value::string(QuestionText);
obj[U("AnswerLatitude")] = json::value::number(AnswerLatitude);
obj[U("AnswerLongitude")] = json::value::number(AnswerLongitude);
ID = id;
table->update(ID, obj);
}

C++/CX WinRT File Copy

I'm really suffering through the WinRT Windows::Storage namespace with all it's asyncronousness.
I have the following private members in my header file:
//Members for copying the SQLite db file
Platform::String^ m_dbName;
Windows::Storage::StorageFolder^ m_localFolder;
Windows::Storage::StorageFolder^ m_installFolder;
Windows::Storage::StorageFile^ m_dbFile;
And I have the following code block in my implementation file:
//Make sure the SQLite Database is in ms-appdata:///local/
m_dbName = L"DynamicSimulations.db";
m_localFolder = ApplicationData::Current->LocalFolder;
m_installFolder = Windows::ApplicationModel::Package::Current->InstalledLocation;
auto getLocalFileOp = m_localFolder->GetFileAsync(m_dbName);
getLocalFileOp->Completed = ref new AsyncOperationCompletedHandler<StorageFile^>([this](IAsyncOperation<StorageFile^>^ operation, AsyncStatus status)
{
m_dbFile = operation->GetResults();
if(m_dbFile == nullptr)
{
auto getInstalledFileOp = m_installFolder->GetFileAsync(m_dbName);
getInstalledFileOp->Completed = ref new AsyncOperationCompletedHandler<StorageFile^>([this](IAsyncOperation<StorageFile^>^ operation, AsyncStatus status)
{
m_dbFile = operation->GetResults();
m_dbFile->CopyAsync(m_localFolder, m_dbName);
});
}
});
I get a memory access violation when it gets to m_dbFile = operation->GetResults();
What am I missing here? I come from a c# background in which this is really easy stuff to do :/
I've tried using '.then' instead of registering the event but I couldn't even get those to compile.
thank you for your help!
If you are interested in the WinRT solution, here it is:
It seems all you want to do is to copy the DB file from the installed location into the local folder. For that the following code should suffice:
//Make sure the SQLite Database is in ms-appdata:///local/
m_dbName = L"DynamicSimulations.db";
m_localFolder = ApplicationData::Current->LocalFolder;
m_installFolder = Windows::ApplicationModel::Package::Current->InstalledLocation;
create_task(m_installFolder->GetFileAsync(m_dbName)).then([this](StorageFile^ file)
{
create_task(file->CopyAsync(m_localFolder, m_dbName)).then([this](StorageFile^ copiedFile)
{
// do something with copiedFile
});
});
I've tried this thing before. Don't do this:
if(m_dbFile == nullptr)
Instead verify the value of "status".
if(status == AsyncStatus::Error)

Unable to set Reporting Services Parameters

I'm generating a reporting services report from an ASP.NET (MVC) based application but am having problems setting the parameters for the report.
I believe the issue has only occurred since we upgraded SQL Server from 2005 to 2008 R2 (and Reporting Services along with it).
The original error encountered was from calling rsExec.Render:
Procedure or function 'pCommunication_ReturnRegistrationLetterDetails'
expects parameter '#guid', which was not supplied.
Debugging the code I noticed that rsExec.SetExecutionParameters is returning the following response:
Cannot call 'NameOfApp.SQLRSExec.ReportExecutionService.SetExecutionParameters(NameOfApp.SQLRSExec.ParameterValue[],
string)' because it is a web method.
Here is the function in it's entirety:
public static bool ProduceReportToFile(string reportname, string filename, string[,] reportparams,
string fileformat)
{
bool successful = false;
SQLRS.ReportingService2005 rs = new SQLRS.ReportingService2005();
SQLRSExec.ReportExecutionService rsExec = new NameOfApp.SQLRSExec.ReportExecutionService();
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
rsExec.Credentials = System.Net.CredentialCache.DefaultCredentials;
// Prepare Render arguments
string historyID = null;
string deviceInfo = null;
// Prepare format - available options are "PDF","Word","CSV","TIFF","XML","EXCEL"
string format = fileformat;
Byte[] results;
string encoding = String.Empty;
string mimeType = String.Empty;
string extension = String.Empty;
SQLRSExec.Warning[] warnings = null;
string[] streamIDs = null;
// Define variables needed for GetParameters() method
// Get the report name
string _reportName = reportname;
string _historyID = null;
bool _forRendering = false;
SQLRS.ParameterValue[] _values = null;
SQLRS.DataSourceCredentials[] _credentials = null;
SQLRS.ReportParameter[] _parameters = null;
// Get if any parameters needed.
_parameters = rs.GetReportParameters(_reportName, _historyID,
_forRendering, _values, _credentials);
// Load the selected report.
SQLRSExec.ExecutionInfo ei =
rsExec.LoadReport(_reportName, historyID);
// Prepare report parameter.
// Set the parameters for the report needed.
SQLRSExec.ParameterValue[] parameters =
new SQLRSExec.ParameterValue[1];
// Place to include the parameter.
if (_parameters.Length > 0)
{
for (int i = 0; i < _parameters.Length; i++)
{
parameters[i] = new SQLRSExec.ParameterValue();
parameters[i].Label = reportparams[i,0];
parameters[i].Name = reportparams[i, 0];
parameters[i].Value = reportparams[i, 1];
}
}
rsExec.SetExecutionParameters(parameters, "en-us");
results = rsExec.Render(format, deviceInfo,
out extension, out encoding,
out mimeType, out warnings, out streamIDs);
// Create a file stream and write the report to it
using (FileStream stream = System.IO.File.OpenWrite(filename))
{
stream.Write(results, 0, results.Length);
}
successful = true;
return successful;
}
Any ideas why I'm now unable to set parameters? The report generation works without issue if parameters aren't required.
Looks like it may have been an issue with how reporting services passes parameters through to the stored procedure providing the data. A string guid was being passed through to the report and the stored procedure expected a varchar guid. I suspect reporting services may have been noticing the string followed the guid format pattern and so passed it through as a uniqueidentifier to the stored procedure.
I changed the data source for the report from "stored procedure" to "text" and set the SQL as "EXEC pMyStoredOProcName #guid".
Please note the guid being passed in as a string to the stored procedure is probably not best practice... I was simply debugging an issue with another developers code.
Parameter _reportName cannot be null or empty. The [CLASSNAME].[METHODNAME]() reflection API could not create and return the SrsReportNameAttribute object
In this specific case it looks like an earlier full compile did not finish.
If you encounter this problem I would suggest that you first compile the class mentioned in the error message and see if this solves the problem.
go to AOT (get Ctrl+D)
in classes find CLASSNAME
3.compile it (F7)