locked
Write a file using fopen in metro?

    Question

  • We tried to develop a metro style app recently and we need some static lib, but the lib is for desktop mode app. And we found out that it tries to open a local file to write some bytes in it, using 

    fopen_s(&fp, "image.jpg", "wb");

    but it returns a error code 13, permission denied.

    However, the lib also tries to read this file with

    fopen_s(&fp, "image.jpg", "rb");

    and it succeeds. So does it means that only writing to a file needs permission while reading needs not?

    We couldn't change the lib so we just cannot replace the fopen_s with other commands such as StorageFile. And the file "image.jpg" is located in the debug\App\AppX. Is this a wrong path?

    Thanks very much.

    Friday, November 9, 2012 8:08 AM

Answers

  • fopen can be used for reading in APPX (.) path and R/W in local data (ApplicationData::Current->LocalFolder) .

    Other path need the Runtime Broker to CreateFile for you, must use async IO.


    Win8 Developer QQ Group 95331609

    • Marked as answer by gsdmzht Monday, November 12, 2012 2:12 AM
    Sunday, November 11, 2012 10:22 AM
  • See Local application data . You will need to query the StorageFolder from Windows.Storage.ApplicationData.Current.LocalFolder and then get its path (in this case the StorageFolder will have a path, but other StorageFolders may not be backed by file system directories and so won't have paths).

    --Rob

    • Marked as answer by gsdmzht Monday, November 12, 2012 2:12 AM
    Monday, November 12, 2012 12:40 AM
    Owner

All replies

  • You need write access to open a file for writing. You need read access to open it for reading.

    Windows Store apps have write access only to their application data directories. They also have read access to their install directory.

    Any other locations are available only via the StorageItem brokers. The app cannot read them directly, but a broker process can open the files and return the contents via the StorageFile's stream.

    --Rob

    Friday, November 9, 2012 10:01 PM
    Owner
  • File operations under Metro are asynchronous and so need quite a bit of code to handle them.

    I enclose a read file example from a program of mine. Just delete the superfluous bits peculiar to my application.

        //pick pcb      
    	FileOpenPicker^ openPicker = ref new FileOpenPicker();
    	openPicker->ViewMode = PickerViewMode::List;   //or Thumbnail;
    	openPicker->SuggestedStartLocation = PickerLocationId::PicturesLibrary;
        openPicker->FileTypeFilter->Append(".pcb");
    
    	
    		task<StorageFile^> fileTask(openPicker->PickSingleFileAsync());
    	fileTask.then([=](StorageFile^ file) {
    
    		if (file==nullptr)
    			return;
    
    
    
    		String^ fileName="4000.pcb"; 
    
    
    		fileName=file->Name;
    		previousfname=fileName;
    		gerberfilename=file->DisplayName; //get name with no extension !!!
    	
    	StorageFolder^ item = KnownFolders::PicturesLibrary;
     
      auto getFileOp = item->GetFileAsync(fileName);
      getFileOp->Completed = ref new AsyncOperationCompletedHandler<StorageFile^>
        ([=](IAsyncOperation<StorageFile^>^ operation, AsyncStatus status)
      {
        auto storageFile = operation->GetResults();
        auto openOp = storageFile->OpenAsync(FileAccessMode::Read);
        openOp->Completed = 
          ref new AsyncOperationCompletedHandler <IRandomAccessStream^>
          ([=](IAsyncOperation<IRandomAccessStream^>^ operation, AsyncStatus status)
        {
          auto istream = operation->GetResults();
          auto dr = ref new DataReader(istream);
          auto loadOp = dr->LoadAsync(istream->Size);
          loadOp->Completed = ref new AsyncOperationCompletedHandler<UINT>
            ([=](IAsyncOperation<UINT>^ operation, AsyncStatus status)
          {
            auto bytesRead = operation->GetResults();
    
    
    		int cx,wurd,dx;	
    		wurd=0;
               //wurd=(UINT16)rev(dr->ReadUInt16());
    
    
    		
                ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
                //{load SYMBOLS}
    
                wurd=(UINT16)rev(dr->ReadUInt16());
                cx = wurd;
                wurd=(UINT16)rev(dr->ReadUInt16());
                cx = cx + (wurd * 65536);
    
                for (dx = 1; dx <= cx; dx++)
                {
                    wurd=(UINT16)rev(dr->ReadUInt16());
                    symboldata[dx] = wurd;
                }
    
                ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
                //{load TRACKS}
                wurd=(UINT16)rev(dr->ReadUInt16());
                cx = wurd;
                wurd=(UINT16)rev(dr->ReadUInt16());
                cx = cx + (wurd * 65536);
    
                for (dx = 1; dx <= cx; dx++)
                {
                    wurd=(UINT16)rev(dr->ReadUInt16());
                    trackdata[dx] = wurd;
                }
    
    
                ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
                //{load PADS}
                wurd=(UINT16)rev(dr->ReadUInt16());
                cx = wurd;
                wurd=(UINT16)rev(dr->ReadUInt16());
                cx = cx + (wurd * 65536);
    
                for (dx = 1; dx <= cx; dx++)
                {
                    wurd=(UINT16)rev(dr->ReadUInt16());
                    //	{padata[cx]=wurd;}
                }
    
    
                ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
                //{load TEXT}
                wurd=(UINT16)rev(dr->ReadUInt16());
                cx = wurd;
                wurd=(UINT16)rev(dr->ReadUInt16());
                cx = cx + (wurd * 65536);
    
                for (dx = 1; dx <= cx; dx++)
                {
                    wurd=(UINT16)rev(dr->ReadUInt16());
                    textdata[dx] = wurd;
                }
    
    
    
                ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
                //{load CONS}
                wurd=(UINT16)rev(dr->ReadUInt16());
                cx = wurd;
                wurd=(UINT16)rev(dr->ReadUInt16());
                cx = cx + (wurd * 65536);
    
                for (dx = 1; dx <= cx; dx++)
                {
                    wurd=(UINT16)rev(dr->ReadUInt16());
                    //	{condata[dx]=wurd;}
                }
    
    
    
    
    
                ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
                //{load INTLIB}
    
    
                wurd=(UINT16)rev(dr->ReadUInt16());
                cx = wurd;
                wurd=(UINT16)rev(dr->ReadUInt16());
                cx = cx + (wurd * 65536);
    
                for (dx = 1; dx <= cx; dx++)
                {
                    wurd=(UINT16)rev(dr->ReadUInt16());
                    slibrary[dx] = wurd;
                }
    
    			dr->DetachStream();
    
    
               
    
    
            
          });
        });
      });
    
      });
    	
    			  
    }
    
    


    n.Wright

    Saturday, November 10, 2012 9:38 PM
  • Hi Rob

    Thanks very much for your reply. I'm quite new to metro style app development, so I wonder that when I'm using VS for development an APP, where is the application data directories you mentioned? 

    Thanks again.

    Sunday, November 11, 2012 7:24 AM
  • Hi Wrightyplp

    Thanks for your reply.

    So you meant that I just cannot use fopen_s in metro app development? I need a lib in my app and this lib just uses fopen_s. So it's the best situation that fopen_s can be used in metro and I can still use this lib. Otherwise, I need to study the codes of the lib and then modify it :-(.

    Thanks you. :-)

    Sunday, November 11, 2012 7:29 AM
  • fopen can be used for reading in APPX (.) path and R/W in local data (ApplicationData::Current->LocalFolder) .

    Other path need the Runtime Broker to CreateFile for you, must use async IO.


    Win8 Developer QQ Group 95331609

    • Marked as answer by gsdmzht Monday, November 12, 2012 2:12 AM
    Sunday, November 11, 2012 10:22 AM
  • See Local application data . You will need to query the StorageFolder from Windows.Storage.ApplicationData.Current.LocalFolder and then get its path (in this case the StorageFolder will have a path, but other StorageFolders may not be backed by file system directories and so won't have paths).

    --Rob

    • Marked as answer by gsdmzht Monday, November 12, 2012 2:12 AM
    Monday, November 12, 2012 12:40 AM
    Owner
  • Thanks very much! It works!
    Monday, November 12, 2012 2:13 AM
  • Thank you very much for your patience and detailed help! It finally works.  
    Monday, November 12, 2012 2:14 AM