I am developing a Windows 8 Metro app, and we intend to deploy it to only a few tablets within our company. It\'s not meant for the Windows Store.
We need the app to
Below is the code that manages to write a file to a network share from WinRT device (Microsoft Surface RT) running Windows 8.1 RT. The essential bits are that:
The basic mechanism is described here: http://msdn.microsoft.com/en-US/library/windows/apps/hh967755.aspx
As a bonus, this shows how to capture output to standard output in a WinRT application.
The code:
#include "App.xaml.h"
#include "MainPage.xaml.h"
#include <ppltasks.h>
using namespace TestApp;
using namespace Platform;
using namespace Windows::UI::Xaml::Navigation;
using namespace Concurrency;
// Anything that is written to standard output in this function will be saved to a file on a network share
int MAIN(int argc, char** argv)
{
printf("This is log output that is saved to a file on a network share!\n");
return 0;
}
static char buffer[1024*1024];
Windows::Foundation::IAsyncOperation<int>^ MainPage::RunAsync()
{
return create_async([this]()->int {
return MAIN(1, NULL);
});
}
using namespace concurrency;
using namespace Platform;
using namespace Windows::Storage;
using namespace Windows::System;
void MainPage::Run()
{
//capture stdout in buffer
setvbuf(stdout, buffer, _IOFBF, sizeof(buffer));
task<int> testTask(RunAsync());
testTask.then([this](int test_result)
{
size_t origsize = strlen(buffer) + 1;
wchar_t* wcstring = new wchar_t[sizeof(buffer)* sizeof(wchar_t)];
size_t converted_chars = 0;
mbstowcs_s(&converted_chars, wcstring, origsize, buffer, _TRUNCATE);
String^ contents = ref new Platform::String(wcstring);
delete [] wcstring;
Platform::String^ Filename = "log_file.txt";
Platform::String^ FolderName = "\\\\MY-SHARE\\shared-folder";
create_task(Windows::Storage::StorageFolder::GetFolderFromPathAsync(FolderName)).then([this, Filename, contents](StorageFolder^ folder)
{
create_task(folder->CreateFileAsync(Filename, CreationCollisionOption::ReplaceExisting)).then([this, contents](StorageFile^ file)
{
create_task(FileIO::WriteTextAsync(file, contents)).then([this, file, contents](task<void> task)
{
try
{
task.get();
OutputBox->Text = ref new Platform::String(L"File written successfully!");
}
catch (COMException^ ex)
{
OutputBox->Text = ref new Platform::String(L"Error writing file!");
}
});
});
});
});
}
MainPage::MainPage()
{
InitializeComponent();
Run();
}
The manifest:
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest">
<Identity Name="6f9dc943-75a5-4195-8a7f-9268fda4e548" Publisher="CN=Someone" Version="1.1.0.1" />
<Properties>
<DisplayName>TestApp</DisplayName>
<PublisherDisplayName>Someone</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
<Description>TestApp</Description>
</Properties>
<Prerequisites>
<OSMinVersion>6.3</OSMinVersion>
<OSMaxVersionTested>6.3</OSMaxVersionTested>
</Prerequisites>
<Resources>
<Resource Language="x-generate" />
</Resources>
<Applications>
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="TestApp.App">
<m2:VisualElements DisplayName="TestApp" Description="TestApp" BackgroundColor="#222222" ForegroundText="light" Square150x150Logo="Assets\Logo.png" Square30x30Logo="Assets\SmallLogo.png">
<m2:DefaultTile>
<m2:ShowNameOnTiles>
<m2:ShowOn Tile="square150x150Logo" />
</m2:ShowNameOnTiles>
</m2:DefaultTile>
<m2:SplashScreen Image="Assets\SplashScreen.png" />
</m2:VisualElements>
<Extensions>
<Extension Category="windows.fileTypeAssociation">
<FileTypeAssociation Name="text">
<DisplayName>Text file</DisplayName>
<SupportedFileTypes>
<FileType ContentType="text/plain">.txt</FileType>
</SupportedFileTypes>
</FileTypeAssociation>
</Extension>
</Extensions>
</Application>
</Applications>
<Capabilities>
<Capability Name="musicLibrary" />
<Capability Name="picturesLibrary" />
<Capability Name="videosLibrary" />
<Capability Name="internetClient" />
<Capability Name="internetClientServer" />
<Capability Name="enterpriseAuthentication" />
<Capability Name="privateNetworkClientServer" />
</Capabilities>
</Package>
Here is a quickstart on file access in JavaScript and VB/C#/C++.
In addition, this article on file access and permissions in Windows Store apps might be useful. From this article, it looks like you are using the right capabilities, but there is a note:
Note: You must add File Type Associations to your app manifest that declare specific file types that your app can access in this location.
This makes sense with the error message that you're seeing. Can you try that? Here's an article on how to do it: http://msdn.microsoft.com/en-us/library/windows/apps/hh452684.aspx
I'm also assuming that you've already checked and ensured that the file that you want to access is not marked with the system or hidden file attributes (as per the error message).
Have a look at this question: Accessing Network shared paths in WinRT
There is no way to access the shared location in Win8 App.
We're currently working around this by accessing the file share through a WCF Web Service
. It's far from ideal, but it gets us what we need.