【问题标题】:Windows 8 Metro App File Share AccessWindows 8 Metro 应用程序文件共享访问
【发布时间】:2013-02-23 04:57:43
【问题描述】:

我正在开发一个 Windows 8 Metro 应用程序,我们打算将它部署到我们公司内的几台平板电脑上。它不适用于 Windows 应用商店。

我们需要应用访问公司网络共享上的一些目录,但强制用户使用FilePicker 不是我们想要的。

我们的第一次尝试是使用await StorageFolder.GetFolderFromPathAsync("J:\\");。这不起作用,并产生了以下异常:

“System.UnauthorizedAccessException”类型的未处理异常发生在 mscorlib.dll

WinRT 信息:无法访问指定的文件或文件夹 (J:\)。 该项目不在应用程序可以访问的位置 (包括应用程序数据文件夹、可通过以下方式访问的文件夹 StorageApplicationPermissions 中的功能和持久化项目 列表)。验证该文件未标记系统或隐藏文件 属性。

附加信息:访问被拒绝。 (HRESULT 的例外情况: 0x80070005 (E_ACCESSDENIED))

所以我们尝试用驱动器映射到的网络路径替换"J:\"。这也不起作用,我们得到了这个异常:

在 mscorlib.dll 中发生了“System.UnauthorizedAccessException”类型的未处理异常

WinRT 信息:无法访问指定的文件 (\\domain\path\JDrive)。验证是否在清单中为此类文件声明了文件类型关联,并且该文件未使用系统或隐藏文件属性进行标记。

附加信息:访问被拒绝。 (来自 HRESULT 的异常:0x80070005 (E_ACCESSDENIED))

我们的应用具有以下功能:

  • 企业认证
  • 互联网(客户端)
  • 专用网络(客户端和服务器)

我们的应用没有声明

这对于 Windows 应用商店应用程序来说是非常合理的,但是对于不进入应用商店的简单内部应用程序是否有任何解决方法?

【问题讨论】:

  • 我也有类似的问题,你找到解决办法了吗?
  • @milan-j 我下面的回答仍然是我们目前的解决方案。如果您能找到其他方法,请发布您自己的答案。

标签: c# windows-8 microsoft-metro


【解决方案1】:

这是JavaScriptVB/C#/C++ 中文件访问的快速入门。

此外,file access and permissions in Windows Store apps 上的这篇文章可能会有用。从这篇文章来看,您似乎使用了正确的功能,但有一个注意事项:

注意:您必须将文件类型关联添加到您的应用清单中 声明您的应用可以在此位置访问的特定文件类型。

这与您看到的错误消息有关。你能试试吗?这是一篇关于如何做到这一点的文章:http://msdn.microsoft.com/en-us/library/windows/apps/hh452684.aspx

我还假设您已经检查并确保您要访问的文件未标记系统或隐藏文件属性(根据错误消息)。

【讨论】:

  • 我在 C# 快速入门指南中没有找到任何对我有帮助的内容。 KnownFoldersFilePickers 的资源有,msdn.microsoft.com/en-us/library/windows/apps/xaml/… 列出了 UNC 文件夹所需的功能,但我们已经有了这些功能,但仍然无法访问网络共享。我添加了一个 .png 文件类型关联声明,但两个异常消息是相同的。
【解决方案2】:

我们目前正在通过WCF Web Service 访问文件共享来解决此问题。这远非理想,但它可以满足我们的需要。

【讨论】:

    【解决方案3】:

    看看这个问题:Accessing Network shared paths in WinRT

    在 Win8 App 中无法访问共享位置。

    【讨论】:

    • 嗯,我能够做到这一点(见我的回答)!有人可以解释为什么这个特殊案例对我有用,但对其他人不起作用?我没有使用任何选择器。在运行应用程序之前,我曾使用 Windows 资源管理器访问过共享位置。
    【解决方案4】:

    下面是管理从运行 Windows 8.1 RT 的 WinRT 设备 (Microsoft Surface RT) 将文件写入网络共享的代码。重要的一点是:

    • 使用 UNC 路径访问共享
    • 分享是公开的
    • 应用程序清单提到了写入的文件类型
    • 应用程序具有适当的功能

    这里描述了基本机制: http://msdn.microsoft.com/en-US/library/windows/apps/hh967755.aspx

    作为奖励,这显示了如何在 WinRT 应用程序中将输出捕获到标准输出。

    代码:

    #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();
    }
    

    清单:

    <?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>
    

    【讨论】:

    • 这看起来可能对日志文件有用,但它可以从网络读取吗?它可以读取文件夹的内容吗?文件名可以在运行时更改吗?
    • 绝对可以把文件夹内容变红。使用 create_task(folder->GetItemsAsync()).then([this] (Windows::Foundation::Collections::IVectorView<:storage::istorageitem>^ items) {...});它可能还可以对文件夹执行其他操作。
    猜你喜欢
    • 1970-01-01
    • 2012-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多